Snap for 6439596 from d12bfa398c56027290a9e6e4fd14f635458ec581 to qt-aml-tzdata-release

Change-Id: If4916a588c0e85189c29cccd566a4ac49ec6328e
diff --git a/Android.bp b/Android.bp
index 83c232b..4268636 100644
--- a/Android.bp
+++ b/Android.bp
@@ -14,8 +14,8 @@
 // limitations under the License.
 //
 
-version_name = "1.23-asop"
-version_code = "417000410"
+version_name = "1.20-asop"
+version_code = "417000328"
 
 android_app {
     name: "LiveTv",
@@ -44,13 +44,16 @@
     static_libs: [
         "android-support-annotations",
         "android-support-compat",
-        "android-support-v7-recyclerview",
-        "androidx.legacy_legacy-support-core-ui",
-        "androidx.leanback_leanback",
-        "androidx.leanback_leanback-preference",
-        "androidx.palette_palette",
-        "androidx.preference_preference",
+        "android-support-core-ui",
         "androidx.tvprovider_tvprovider",
+        "android-support-v4",
+        "android-support-v7-appcompat",
+        "android-support-v7-palette",
+        "android-support-v7-preference",
+        "android-support-v7-recyclerview",
+        "android-support-v14-preference",
+        "android-support-v17-leanback",
+        "android-support-v17-preference-leanback",
         "jsr330",
         "live-channels-partner-support",
         "live-tv-tuner-proto",
@@ -59,7 +62,6 @@
         "tv-auto-factory-jar",
         "tv-common",
         "tv-error-prone-annotations-jar",
-        "tv-javax-annotations-jar",
         "tv-lib-dagger",
         "tv-lib-exoplayer",
         "tv-lib-exoplayer-v2-core",
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 7110160..a398823 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -16,12 +16,12 @@
 -->
 <!-- This manifest is for LiveTv -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
+  xmlns:tools="http://schemas.android.com/tools"
     package="com.android.tv" >
 
     <uses-sdk
         android:minSdkVersion="23"
-        android:targetSdkVersion="28" />
+        android:targetSdkVersion="27" />
 
     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
@@ -79,7 +79,8 @@
         android:label="@string/app_name"
         android:supportsRtl="true"
         android:theme="@style/Theme.TV"
-        tools:replace="android:appComponentFactory" >
+        tools:replace="android:appComponentFactory">
+        >
 
         <!-- providers are listed here to keep them separate from the internal versions -->
         <provider
@@ -253,16 +254,12 @@
             android:name="com.android.tv.recommendation.ChannelPreviewUpdater$ChannelPreviewUpdateService"
             android:permission="android.permission.BIND_JOB_SERVICE" />
 
-        <receiver
-            android:name="com.android.tv.receiver.BootCompletedReceiver"
-            android:exported="true" >
+        <receiver android:name="com.android.tv.receiver.BootCompletedReceiver" >
             <intent-filter>
                 <action android:name="android.intent.action.BOOT_COMPLETED" />
             </intent-filter>
         </receiver>
-        <receiver
-            android:name="com.android.tv.receiver.PackageIntentsReceiver"
-            android:exported="true" >
+        <receiver android:name="com.android.tv.receiver.PackageIntentsReceiver" >
             <intent-filter>
                 <action android:name="android.intent.action.PACKAGE_ADDED" />
                 <!-- PACKAGE_CHANGED for package enabled/disabled notification -->
@@ -293,13 +290,11 @@
             android:name="com.android.tv.dvr.recorder.DvrRecordingService"
             android:label="@string/dvr_service_name" />
 
-        <receiver
-            android:name="com.android.tv.dvr.recorder.DvrStartRecordingReceiver"
-            android:exported="false" />
+        <receiver android:name="com.android.tv.dvr.recorder.DvrStartRecordingReceiver" />
 
         <service
             android:name="com.android.tv.data.epg.EpgFetchService"
             android:permission="android.permission.BIND_JOB_SERVICE" />
     </application>
 
-</manifest>
\ No newline at end of file
+</manifest>
diff --git a/README.md b/README.md
index 0659bbd..63c1f44 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,18 @@
 
 __Live TV__ is the Open Source reference application for watching TV on Android TVs.
 
+## Source
+
+The source of truth is an internal google repository (aka google3) at
+cs/third_party/java_src/android_app/live_channels
+
+Changes are made in the google3 repository and automatically pushed here.
+
+The following files are only in the android repository and must be changed there.
+
+* *.mk
+* \*\*/lib/\*.\*
+
 ## AOSP instructions
 
 To install LiveTv
diff --git a/assets/rating_sources.html b/assets/rating_sources.html
index ff4a005..50da7cc 100644
--- a/assets/rating_sources.html
+++ b/assets/rating_sources.html
@@ -89,22 +89,4 @@
 <pre>
     Source: http://www.mpaa.org/film-ratings/
 </pre>
-<ul>
-    <li>TV content rating system strings for DTMB</li>
-</ul>
-<pre>
-    Source: http://www.gb688.cn/bzgk/gb/newGbInfo?hcno=59E83CA701AEB4248E115BC043688FEC
-</pre>
-<ul>
-    <li>Implementations details of TV content rating system strings for New Zealand</li>
-</ul>
-<pre>
-    Source: https://bsa.govt.nz/images/03_BSA_FREE-TO-AIR-TV_CLASSIFICATIONS_DRAFT.pdf
-</pre>
-<ul>
-    <li>TV content rating system strings for Thailand</li>
-</ul>
-<pre>
-    Source: https://broadcast.nbtc.go.th/law/dwl.php?id=NjAwODAwMDAwMDAx&file=ZGF0YS9kb2N1bWVudC9sYXcvZG9jL3RoLzYwMDgwMDAwMDAwMS5wZGY=
-</pre>
 </body></html>
diff --git a/build.gradle b/build.gradle
index 10cddcc..23e3dbd 100644
--- a/build.gradle
+++ b/build.gradle
@@ -18,28 +18,37 @@
 /*
  * Experimental gradle configuration.  This file may not be up to date.
  */
-apply plugin: 'com.android.application'
 
 buildscript {
     repositories {
+        mavenCentral()
         google()
-        jcenter()
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:3.4.2'
-        classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.10'
+        classpath 'com.android.tools.build:gradle:3.1.4'
+        classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.6'
     }
 }
-
+apply plugin: 'com.android.application'
 android {
     compileSdkVersion 28
     buildToolsVersion '28.0.3'
-
-    compileOptions() {
-        sourceCompatibility JavaVersion.VERSION_1_8
-        targetCompatibility JavaVersion.VERSION_1_8
+    dexOptions {
+        preDexLibraries = false
+        additionalParameters=['--core-library']
+        javaMaxHeapSize "6g"
     }
-
+    android {
+        defaultConfig {
+            resConfigs "en"
+        }
+    }
+    defaultConfig {
+        minSdkVersion 23
+        targetSdkVersion 28
+        versionCode 1
+        versionName "1.0"
+    }
     buildTypes {
         debug {
             minifyEnabled false
@@ -48,15 +57,10 @@
             minifyEnabled true
         }
     }
-
-    defaultConfig {
-        minSdkVersion 23
-        resConfigs "en"
-        targetSdkVersion 28
-        versionCode 1
-        versionName "1.0"
+    compileOptions() {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
     }
-
     sourceSets {
         main {
             res.srcDirs = ['res', 'material_res']
@@ -66,33 +70,30 @@
     }
 }
 
-allprojects {
-    repositories {
-        google()
-        jcenter()
-    }
+repositories {
+    mavenCentral()
+    jcenter()
+    google()
 }
 
 dependencies {
-    implementation      'androidx.appcompat:appcompat:1.0.2'
-    implementation      'androidx.core:core:1.0.2'
-    implementation      'androidx.palette:palette:1.0.0'
-    implementation      'androidx.leanback:leanback:1.1.0-alpha02'
-    implementation      'androidx.recyclerview:recyclerview:1.0.0'
-    implementation      'androidx.recyclerview:recyclerview-selection:1.0.0'
-    implementation      'androidx.tvprovider:tvprovider:1.0.0'
+    implementation 'androidx.appcompat:appcompat:1.0.2'
+    implementation 'androidx.palette:palette:1.0.0'
+    implementation 'androidx.leanback:leanback:1.0.0'
+    implementation "androidx.tvprovider:tvprovider:1.0.0"
+    implementation "androidx.recyclerview:recyclerview:1.0.0"
+    implementation "androidx.recyclerview:recyclerview-selection:1.0.0"
+    implementation "androidx.palette:palette:1.0.0"
 
-    annotationProcessor 'com.google.auto.factory:auto-factory:1.0-beta6'
-    implementation      'com.google.auto.factory:auto-factory:1.0-beta6'
-    annotationProcessor 'com.google.auto.value:auto-value:1.5.3'
-    implementation      'com.google.auto.value:auto-value:1.5.3'
-    implementation      'com.google.dagger:dagger:2.23'
-    implementation      'com.google.dagger:dagger-android:2.23'
-    annotationProcessor 'com.google.dagger:dagger-android-processor:2.23'
-    annotationProcessor 'com.google.dagger:dagger-compiler:2.23'
-    implementation      'com.google.guava:guava:28.0-jre'
+    implementation 'com.google.dagger:dagger:2.18'
+    implementation 'com.google.dagger:dagger-android:2.18'
+    annotationProcessor 'com.google.dagger:dagger-compiler:2.18'
+    annotationProcessor 'com.google.dagger:dagger-android-processor:2.18'
 
-    implementation      'javax.inject:javax.inject:1'
-
-    implementation      project(':common')
-}
+    /*Not building with  latest one (1.6.3)*/
+    annotationProcessor 'com.google.auto.value:auto-value:1.5.4'
+    implementation 'com.google.auto.value:auto-value:1.5.4'
+    implementation 'javax.inject:javax.inject:1'
+    implementation 'com.google.guava:guava:26.0-android'
+    implementation project(':common')
+}
\ No newline at end of file
diff --git a/common/Android.bp b/common/Android.bp
index 728587f..63759d4 100644
--- a/common/Android.bp
+++ b/common/Android.bp
@@ -28,28 +28,22 @@
     resource_dirs: ["res"],
 
     libs: [
-        "android-support-annotations",
         "tv-auto-value-jar",
         "tv-auto-factory-jar",
+        "android-support-annotations",
         "tv-error-prone-annotations-jar",
-        "tv-javax-annotations-jar",
-
+        "tv-guava-android-jar",
+        "jsr330",
+        "tv-lib-dagger",
+        "tv-lib-exoplayer",
+        "tv-lib-exoplayer-v2-core",
+        "android-support-compat",
+        "android-support-core-ui",
+        "android-support-v7-recyclerview",
+        "android-support-v17-leanback",
     ],
 
-    static_libs: [
-            "androidx.legacy_legacy-support-core-ui",
-            "androidx.appcompat_appcompat",
-            "androidx.preference_preference",
-            "androidx.leanback_leanback",
-            "androidx.tvprovider_tvprovider",
-            "tv-guava-android-jar",
-            "tv-guava-failureaccess-jar",
-            "jsr330",
-            "tv-lib-dagger",
-            "tv-lib-exoplayer",
-            "tv-lib-exoplayer-v2-core",
-            "tv-lib-dagger-android",
-    ],
+    static_libs: ["tv-lib-dagger-android"],
 
     plugins: [
         "tv-auto-value",
diff --git a/common/AndroidManifest.xml b/common/AndroidManifest.xml
index eb7de57..7002d5f 100644
--- a/common/AndroidManifest.xml
+++ b/common/AndroidManifest.xml
@@ -17,6 +17,6 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="com.android.tv.common"
           android:versionCode="1">
-    <uses-sdk android:targetSdkVersion="28" android:minSdkVersion="23"/>
+    <uses-sdk android:targetSdkVersion="27" android:minSdkVersion="23"/>
     <application />
 </manifest>
diff --git a/common/build.gradle b/common/build.gradle
index b7bc886..f371475 100644
--- a/common/build.gradle
+++ b/common/build.gradle
@@ -21,24 +21,37 @@
 
 apply plugin: 'com.android.library'
 apply plugin: 'com.google.protobuf'
-
+buildscript {
+    repositories {
+        mavenCentral()
+        google()
+    }
+    dependencies {
+        classpath 'com.android.tools.build:gradle:3.1.4'
+        classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.6'
+    }
+}
 android {
     compileSdkVersion 28
     buildToolsVersion '28.0.3'
+    dexOptions {
+        preDexLibraries = false
+        additionalParameters = ['--core-library']
+        javaMaxHeapSize "6g"
+    }
 
-    compileOptions() {
-        sourceCompatibility JavaVersion.VERSION_1_8
-        targetCompatibility JavaVersion.VERSION_1_8
+    android {
+        defaultConfig {
+            resConfigs "en"
+        }
     }
 
     defaultConfig {
         minSdkVersion 23
-        resConfigs "en"
         targetSdkVersion 28
         versionCode 1
         versionName "1.0"
     }
-
     buildTypes {
         debug {
             minifyEnabled false
@@ -53,6 +66,10 @@
             buildConfigField "boolean", "NO_JNI_TEST", "false"
         }
     }
+    compileOptions() {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
 
     sourceSets {
         main {
@@ -62,32 +79,29 @@
             proto {
                 srcDir 'src/com/android/tv/common/compat/internal'
             }
-            proto {
-                srcDir 'src/com/android/tv/common/flags/proto'
-            }
         }
     }
 }
 
-dependencies {
-    implementation      'androidx.annotation:annotation:1.1.0'
-    implementation      'androidx.appcompat:appcompat:1.0.2'
-    implementation      'androidx.leanback:leanback:1.1.0-alpha02'
-    implementation      'androidx.palette:palette:1.0.0'
-    implementation      'androidx.recyclerview:recyclerview:1.0.0'
-    implementation      'androidx.recyclerview:recyclerview-selection:1.0.0'
-    implementation      'androidx.tvprovider:tvprovider:1.0.0'
+repositories {
+    mavenCentral()
+    google()
+}
 
-    implementation      'com.google.android.exoplayer:exoplayer:r1.5.16'
-    implementation      'com.google.android.exoplayer:exoplayer-core:2.10.1'
-    annotationProcessor 'com.google.auto.value:auto-value:1.5.3'
-    implementation      'com.google.auto.value:auto-value:1.5.3'
-    implementation      'com.google.dagger:dagger:2.23'
-    implementation      'com.google.dagger:dagger-android:2.23'
-    annotationProcessor 'com.google.dagger:dagger-android-processor:2.23'
-    annotationProcessor 'com.google.dagger:dagger-compiler:2.23'
-    implementation      'com.google.guava:guava:28.0-jre'
-    implementation      'com.google.protobuf:protobuf-java:3.0.0'
+dependencies {
+    implementation 'androidx.appcompat:appcompat:1.0.2'
+    implementation 'androidx.palette:palette:1.0.0'
+    implementation 'androidx.leanback:leanback:1.0.0'
+    implementation "androidx.tvprovider:tvprovider:1.0.0"
+    implementation "androidx.recyclerview:recyclerview:1.0.0"
+    implementation "androidx.recyclerview:recyclerview-selection:1.0.0"
+    implementation "androidx.palette:palette:1.0.0"
+    implementation 'com.google.guava:guava:26.0-android'
+    implementation 'com.google.protobuf:protobuf-java:3.0.0'
+    implementation 'com.google.dagger:dagger:2.18'
+    implementation 'com.google.dagger:dagger-android:2.18'
+    annotationProcessor 'com.google.dagger:dagger-compiler:2.18'
+    annotationProcessor 'com.google.dagger:dagger-android-processor:2.18'
 }
 protobuf {
     // Configure the protoc executable
diff --git a/common/src/com/android/tv/common/BaseApplication.java b/common/src/com/android/tv/common/BaseApplication.java
index 1a42120..45c3256 100644
--- a/common/src/com/android/tv/common/BaseApplication.java
+++ b/common/src/com/android/tv/common/BaseApplication.java
@@ -21,22 +21,17 @@
 import android.os.Build;
 import android.os.StrictMode;
 import android.support.annotation.VisibleForTesting;
-
-import com.android.tv.common.dev.DeveloperPreferences;
 import com.android.tv.common.feature.CommonFeatures;
 import com.android.tv.common.recording.RecordingStorageStatusManager;
 import com.android.tv.common.util.Clock;
 import com.android.tv.common.util.CommonUtils;
 import com.android.tv.common.util.Debug;
-
-import dagger.Lazy;
+import com.android.tv.common.util.SystemProperties;
 import dagger.android.DaggerApplication;
 
-import javax.inject.Inject;
-
-/** The base application class for TV applications. */
+/** The base application class for Live TV applications. */
 public abstract class BaseApplication extends DaggerApplication implements BaseSingletons {
-    @Inject Lazy<RecordingStorageStatusManager> mRecordingStorageStatusManager;
+    private RecordingStorageStatusManager mRecordingStorageStatusManager;
 
     /**
      * An instance of {@link BaseSingletons}. Note that this can be set directly only for the test
@@ -70,7 +65,7 @@
 
         // Only set StrictMode for ENG builds because the build server only produces userdebug
         // builds.
-        if (BuildConfig.ENG && DeveloperPreferences.ALLOW_STRICT_MODE.get(this)) {
+        if (BuildConfig.ENG && SystemProperties.ALLOW_STRICT_MODE.getValue()) {
             StrictMode.ThreadPolicy.Builder threadPolicyBuilder =
                     new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog();
             // TODO(b/69565157): Turn penaltyDeath on for VMPolicy when tests are fixed.
@@ -104,6 +99,9 @@
     @Override
     @TargetApi(Build.VERSION_CODES.N)
     public RecordingStorageStatusManager getRecordingStorageStatusManager() {
-        return mRecordingStorageStatusManager.get();
+        if (mRecordingStorageStatusManager == null) {
+            mRecordingStorageStatusManager = new RecordingStorageStatusManager(this);
+        }
+        return mRecordingStorageStatusManager;
     }
 }
diff --git a/common/src/com/android/tv/common/BaseSingletons.java b/common/src/com/android/tv/common/BaseSingletons.java
index 8a3820d..1053061 100644
--- a/common/src/com/android/tv/common/BaseSingletons.java
+++ b/common/src/com/android/tv/common/BaseSingletons.java
@@ -18,28 +18,15 @@
 
 import com.android.tv.common.buildtype.HasBuildType;
 import com.android.tv.common.flags.has.HasCloudEpgFlags;
+import com.android.tv.common.flags.has.HasConcurrentDvrPlaybackFlags;
 import com.android.tv.common.recording.RecordingStorageStatusManager;
 import com.android.tv.common.util.Clock;
 
 /** Injection point for the base app */
-public interface BaseSingletons extends HasCloudEpgFlags, HasBuildType {
+public interface BaseSingletons
+        extends HasCloudEpgFlags, HasBuildType, HasConcurrentDvrPlaybackFlags {
 
-    /*
-     * Do not add any new methods here.
-     *
-     * To move a getter to Injection.
-     *  1. Make a type injectable @Singleton.
-     *  2. Mark the getter here as deprecated.
-     *  3. Lazily inject the object in TvApplication.
-     *  4. Move easy usages of getters to injection instead.
-     *  5. Delete the method when all usages are migrated.
-     */
-
-    /* @deprecated use injection instead.  */
-    @Deprecated
     Clock getClock();
 
-    /* @deprecated use injection instead.  */
-    @Deprecated
     RecordingStorageStatusManager getRecordingStorageStatusManager();
 }
diff --git a/common/src/com/android/tv/common/buildtype/BuildTypeFactory.java b/common/src/com/android/tv/common/buildtype/BuildTypeFactory.java
deleted file mode 100644
index 706a603..0000000
--- a/common/src/com/android/tv/common/buildtype/BuildTypeFactory.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2019 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.buildtype;
-
-import com.google.common.base.Supplier;
-
-import javax.inject.Inject;
-
-
-/** Factory for {@link HasBuildType.BuildType}.
- *
- * <p>Hardcoded to {@link HasBuildType.BuildType#AOSP}.
- */
-public class BuildTypeFactory implements Supplier<HasBuildType> {
-    private static final HasBuildType INSTANCE = new AospBuildTypeProvider();
-
-    @Inject
-    public BuildTypeFactory() {}
-
-    public static HasBuildType create() {
-        return INSTANCE;
-    }
-
-    @Override
-    public HasBuildType get() {
-        return INSTANCE;
-    }
-}
\ No newline at end of file
diff --git a/common/src/com/android/tv/common/buildtype/BuildTypeModule.java b/common/src/com/android/tv/common/buildtype/BuildTypeModule.java
deleted file mode 100644
index 43f398d..0000000
--- a/common/src/com/android/tv/common/buildtype/BuildTypeModule.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2019 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.buildtype;
-
-import dagger.Module;
-import dagger.Provides;
-import dagger.Reusable;
-
-/** Provides BuildType */
-@Module
-public class BuildTypeModule {
-    private static final HasBuildType.BuildType BUILD_TYPE =
-            BuildTypeFactory.create().getBuildType();
-
-    @Provides
-    @Reusable
-    HasBuildType.BuildType providesBuildType() {
-        return BUILD_TYPE;
-    }
-}
diff --git a/common/src/com/android/tv/common/buildtype/HasBuildType.java b/common/src/com/android/tv/common/buildtype/HasBuildType.java
index addac07..7d5677c 100644
--- a/common/src/com/android/tv/common/buildtype/HasBuildType.java
+++ b/common/src/com/android/tv/common/buildtype/HasBuildType.java
@@ -30,7 +30,5 @@
         PROD
     }
 
-    /** @deprecated use injection instead. */
-    @Deprecated
     BuildType getBuildType();
 }
diff --git a/common/src/com/android/tv/common/compat/TvInputInfoCompat.java b/common/src/com/android/tv/common/compat/TvInputInfoCompat.java
index 2f06d94..685a3ed 100644
--- a/common/src/com/android/tv/common/compat/TvInputInfoCompat.java
+++ b/common/src/com/android/tv/common/compat/TvInputInfoCompat.java
@@ -45,12 +45,13 @@
 
     private final Context mContext;
     private final TvInputInfo mTvInputInfo;
-    private boolean mAudioOnly;
-    private boolean mAudioAttributeInit = false;
+    private final boolean mAudioOnly;
 
     public TvInputInfoCompat(Context context, TvInputInfo tvInputInfo) {
         mContext = context;
         mTvInputInfo = tvInputInfo;
+        // TODO(b/112938832): use tvInputInfo.isAudioOnly() when SDK is updated
+        mAudioOnly = Boolean.parseBoolean(getExtras().get(ATTRIBUTE_NAME_AUDIO_ONLY));
     }
 
     public TvInputInfo getTvInputInfo() {
@@ -58,11 +59,6 @@
     }
 
     public boolean isAudioOnly() {
-        // TODO(b/112938832): use tvInputInfo.isAudioOnly() when SDK is updated
-        if (!mAudioAttributeInit) {
-            mAudioOnly = Boolean.parseBoolean(getExtras().get(ATTRIBUTE_NAME_AUDIO_ONLY));
-            mAudioAttributeInit = true;
-        }
         return mAudioOnly;
     }
 
diff --git a/common/src/com/android/tv/common/compat/internal/recording_commands.proto b/common/src/com/android/tv/common/compat/internal/recording_commands.proto
index c247e78..ce59bfa 100644
--- a/common/src/com/android/tv/common/compat/internal/recording_commands.proto
+++ b/common/src/com/android/tv/common/compat/internal/recording_commands.proto
@@ -19,7 +19,6 @@
 // package and should not be used outside it.
 
 syntax = "proto3";
-
 package android.tv.common.compat.internal;
 
 option java_outer_classname = "RecordingCommands";
diff --git a/common/src/com/android/tv/common/compat/internal/recording_events.proto b/common/src/com/android/tv/common/compat/internal/recording_events.proto
index fffa62a..68db5dd 100644
--- a/common/src/com/android/tv/common/compat/internal/recording_events.proto
+++ b/common/src/com/android/tv/common/compat/internal/recording_events.proto
@@ -18,7 +18,6 @@
 // support new features on older devices. NOTE: this proto is internal to this
 // package and should not be used outside it.
 syntax = "proto3";
-
 package android.tv.common.compat.internal;
 
 option java_outer_classname = "RecordingEvents";
@@ -47,3 +46,4 @@
   // Recording URI.
   string uri = 1;
 }
+
diff --git a/common/src/com/android/tv/common/compat/internal/tif_commands.proto b/common/src/com/android/tv/common/compat/internal/tif_commands.proto
index b69d487..d586770 100644
--- a/common/src/com/android/tv/common/compat/internal/tif_commands.proto
+++ b/common/src/com/android/tv/common/compat/internal/tif_commands.proto
@@ -19,7 +19,6 @@
 // package and should not be used outside it.
 
 syntax = "proto3";
-
 package android.tv.common.compat.internal;
 
 option java_outer_classname = "Commands";
diff --git a/common/src/com/android/tv/common/compat/internal/tif_events.proto b/common/src/com/android/tv/common/compat/internal/tif_events.proto
index b15a884..6e71ae1 100644
--- a/common/src/com/android/tv/common/compat/internal/tif_events.proto
+++ b/common/src/com/android/tv/common/compat/internal/tif_events.proto
@@ -18,7 +18,6 @@
 // support new features on older devices. NOTE: this proto is internal to this
 // package and should not be used outside it.
 syntax = "proto3";
-
 package android.tv.common.compat.internal;
 
 option java_outer_classname = "Events";
diff --git a/common/src/com/android/tv/common/customization/CustomizationManager.java b/common/src/com/android/tv/common/customization/CustomizationManager.java
index 5a29d7c..09ecaef 100644
--- a/common/src/com/android/tv/common/customization/CustomizationManager.java
+++ b/common/src/com/android/tv/common/customization/CustomizationManager.java
@@ -97,8 +97,8 @@
 
     /**
      * 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 TV
-     * app.
+     * 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) {
@@ -156,26 +156,11 @@
 
     private static String getCustomizationPackageName(Context context) {
         if (sCustomizationPackage == null) {
-            sCustomizationPackage = "";
             List<PackageInfo> packageInfos =
                     context.getPackageManager()
                             .getPackagesHoldingPermissions(CUSTOMIZE_PERMISSIONS, 0);
-            if (packageInfos.size() != 0) {
-                /** Iterate through all packages returning the first vendor customizer */
-                for (PackageInfo packageInfo : packageInfos) {
-                    if (packageInfo.packageName.startsWith("com.android") == false) {
-                        sCustomizationPackage = packageInfo.packageName;
-                        break;
-                    }
-                }
-
-                /** If no vendor package found, return first in the list */
-                if (sCustomizationPackage == "") {
-                    sCustomizationPackage = packageInfos.get(0).packageName;
-                }
-            }
+            sCustomizationPackage = packageInfos.size() == 0 ? "" : packageInfos.get(0).packageName;
         }
-
         return sCustomizationPackage;
     }
 
diff --git a/common/src/com/android/tv/common/dagger/ApplicationModule.java b/common/src/com/android/tv/common/dagger/ApplicationModule.java
index be9cf88..4655f77 100644
--- a/common/src/com/android/tv/common/dagger/ApplicationModule.java
+++ b/common/src/com/android/tv/common/dagger/ApplicationModule.java
@@ -21,10 +21,8 @@
 import android.os.Looper;
 import com.android.tv.common.dagger.annotations.ApplicationContext;
 import com.android.tv.common.dagger.annotations.MainLooper;
-import com.android.tv.common.util.Clock;
 import dagger.Module;
 import dagger.Provides;
-import dagger.Reusable;
 
 /**
  * Provides application-scope qualifiers for the {@link Application}, the application context, and
@@ -59,10 +57,4 @@
     ContentResolver provideContentResolver() {
         return mApplication.getContentResolver();
     }
-
-    @Provides
-    @Reusable
-    static Clock providesClock() {
-        return Clock.SYSTEM;
-    }
 }
diff --git a/common/src/com/android/tv/common/dagger/init/SafePreDaggerInitializer.java b/common/src/com/android/tv/common/dagger/init/SafePreDaggerInitializer.java
deleted file mode 100644
index 9465d92..0000000
--- a/common/src/com/android/tv/common/dagger/init/SafePreDaggerInitializer.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2019 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.dagger.init;
-
-import android.content.Context;
-import android.util.Log;
-
-/**
- * Initializes objects one time only.
- *
- * <p>This is needed because ContentProviders can be created before Application.onCreate
- */
-public final class SafePreDaggerInitializer {
-    private interface Initialize {
-        void init(Context context);
-    }
-
-    private static final String TAG = "SafePreDaggerInitializer";
-
-    private static boolean initialized = false;
-    private static Context oldContext;
-
-    private static final Initialize[] sList =
-            new Initialize[] {
-                /* Begin_AOSP_Comment_Out
-                com.google.android.libraries.phenotype.client.PhenotypeContext::setContext
-                End_AOSP_Comment_Out */
-            };
-
-    public static synchronized void init(Context context) {
-        if (!initialized) {
-            for (Initialize i : sList) {
-                i.init(context);
-            }
-            oldContext = context;
-            initialized = true;
-        } else if (oldContext != context) {
-            Log.w(
-                    TAG,
-                    "init called more than once, skipping. Old context was "
-                            + oldContext
-                            + " new context is "
-                            + context);
-        }
-    }
-
-    private SafePreDaggerInitializer() {}
-}
diff --git a/common/src/com/android/tv/common/dev/DeveloperPreference.java b/common/src/com/android/tv/common/dev/DeveloperPreference.java
deleted file mode 100644
index b1c401b..0000000
--- a/common/src/com/android/tv/common/dev/DeveloperPreference.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2019 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.dev;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.support.annotation.Nullable;
-import android.support.annotation.VisibleForTesting;
-
-/** Preferences available to developers */
-public abstract class DeveloperPreference<T> {
-
-    private static final String PREFERENCE_FILE_NAME =
-            "com.android.tv.common.dev.DeveloperPreference";
-
-    /**
-     * Create a boolean developer preference.
-     *
-     * @param key the developer setting key.
-     * @param defaultValue the value to return if the setting is undefined or empty.
-     */
-    public static DeveloperPreference<Boolean> create(String key, boolean defaultValue) {
-        return new DeveloperBooleanPreference(key, defaultValue);
-    }
-
-    @VisibleForTesting
-    static final SharedPreferences getPreferences(Context context) {
-        return context.getSharedPreferences(PREFERENCE_FILE_NAME, Context.MODE_PRIVATE);
-    }
-
-    /**
-     * Create a int developer preference.
-     *
-     * @param key the developer setting key.
-     * @param defaultValue the value to return if the setting is undefined or empty.
-     */
-    public static DeveloperPreference<Integer> create(String key, int defaultValue) {
-        return new DeveloperIntegerPreference(key, defaultValue);
-    }
-
-    final String mKey;
-    final T mDefaultValue;
-    private T mValue;
-
-    private DeveloperPreference(String key, T defaultValue) {
-        mKey = key;
-        mValue = null;
-        mDefaultValue = defaultValue;
-    }
-
-    /** Set the value. */
-    public final void set(Context context, T value) {
-        mValue = value;
-        storeValue(context, value);
-    }
-
-    protected abstract void storeValue(Context context, T value);
-
-    /** Get the current value, or the default if the value is not set. */
-    public final T get(Context context) {
-        mValue = getStoredValue(context);
-        return mValue;
-    }
-
-    /** Get the current value, or the default if the value is not set or context is null. */
-    public final T getDefaultIfContextNull(@Nullable Context context) {
-        return context == null ? mDefaultValue : getStoredValue(context);
-    }
-
-    protected abstract T getStoredValue(Context context);
-
-    /**
-     * Clears the current value.
-     *
-     * <p>Future calls to {@link #get(Context)} will return the default value.
-     */
-    public final void clear(Context context) {
-        getPreferences(context).edit().remove(mKey);
-    }
-
-    @Override
-    public final String toString() {
-        return "[" + mKey + "]=" + mValue + " Default value : " + mDefaultValue;
-    }
-
-    private static final class DeveloperBooleanPreference extends DeveloperPreference<Boolean> {
-
-        private DeveloperBooleanPreference(String key, Boolean defaultValue) {
-            super(key, defaultValue);
-        }
-
-        @Override
-        public void storeValue(Context context, Boolean value) {
-            getPreferences(context).edit().putBoolean(mKey, value).apply();
-        }
-
-        @Override
-        public Boolean getStoredValue(Context context) {
-            return getPreferences(context).getBoolean(mKey, mDefaultValue);
-        }
-    }
-
-    private static final class DeveloperIntegerPreference extends DeveloperPreference<Integer> {
-
-        private DeveloperIntegerPreference(String key, Integer defaultValue) {
-            super(key, defaultValue);
-        }
-
-        @Override
-        protected void storeValue(Context context, Integer value) {
-            getPreferences(context).edit().putInt(mKey, value).apply();
-        }
-
-        @Override
-        protected Integer getStoredValue(Context context) {
-            return getPreferences(context).getInt(mKey, mDefaultValue);
-        }
-    }
-}
diff --git a/common/src/com/android/tv/common/dev/DeveloperPreferences.java b/common/src/com/android/tv/common/dev/DeveloperPreferences.java
deleted file mode 100644
index 9c83b64..0000000
--- a/common/src/com/android/tv/common/dev/DeveloperPreferences.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2019 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.dev;
-
-/** A class about the constants for TV Developer preferences. */
-public final class DeveloperPreferences {
-
-    /**
-     * Allow Google Analytics for eng builds.
-     *
-     * <p>Defaults to {@code false}.
-     */
-    public static final DeveloperPreference<Boolean> ALLOW_ANALYTICS_IN_ENG =
-            DeveloperPreference.create("tv_allow_analytics_in_eng", false);
-
-    /**
-     * Allow Strict mode for debug builds.
-     *
-     * <p>Defaults to {@code true}.
-     */
-    public static final DeveloperPreference<Boolean> ALLOW_STRICT_MODE =
-            DeveloperPreference.create("tv_allow_strict_mode", true);
-
-    /**
-     * When true {@link android.view.KeyEvent}s are logged.
-     *
-     * <p>Defaults to {@code false}.
-     */
-    public static final DeveloperPreference<Boolean> LOG_KEYEVENT =
-            DeveloperPreference.create("tv_log_keyevent", false);
-
-    /**
-     * When true debug keys are used.
-     *
-     * <p>Defaults to {@code false}.
-     */
-    public static final DeveloperPreference<Boolean> USE_DEBUG_KEYS =
-            DeveloperPreference.create("tv_use_debug_keys", false);
-
-    /**
-     * Send {@link com.android.tv.analytics.Tracker} information.
-     *
-     * <p>Defaults to {@code true}.
-     */
-    public static final DeveloperPreference<Boolean> USE_TRACKER =
-            DeveloperPreference.create("tv_use_tracker", true);
-
-    /**
-     * Maximum buffer size in MegaBytes.
-     *
-     * <p>Defaults to 2MB.
-     */
-    public static final DeveloperPreference<Integer> MAX_BUFFER_SIZE_MBYTES =
-            DeveloperPreference.create("tv.tuner.buffersize_mbytes", 2 * 1024);
-
-    private DeveloperPreferences() {}
-}
diff --git a/common/src/com/android/tv/common/experiments/ExperimentFlag.java b/common/src/com/android/tv/common/experiments/ExperimentFlag.java
new file mode 100644
index 0000000..b8370ad
--- /dev/null
+++ b/common/src/com/android/tv/common/experiments/ExperimentFlag.java
@@ -0,0 +1,96 @@
+/*
+ * 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.common.experiments;
+
+import android.support.annotation.VisibleForTesting;
+import com.android.tv.common.BuildConfig;
+
+import com.google.common.base.Supplier;
+
+/** Experiments return values based on user, device and other criteria. */
+public final class ExperimentFlag<T> {
+
+    // NOTE: sAllowOverrides IS NEVER USED in the non AOSP version.
+    private static boolean sAllowOverrides = false;
+
+    @VisibleForTesting
+    public static void initForTest() {
+        /* Begin_AOSP_Comment_Out
+        if (!BuildConfig.AOSP) {
+            PhenotypeFlag.initForTest();
+            return;
+        }
+        End_AOSP_Comment_Out */
+        sAllowOverrides = true;
+    }
+
+    /** Returns a boolean experiment */
+    public static ExperimentFlag<Boolean> createFlag(
+// AOSP_Comment_Out             Supplier<Boolean> phenotypeFlag,
+            boolean defaultValue) {
+        return new ExperimentFlag<>(
+// AOSP_Comment_Out                 phenotypeFlag,
+                defaultValue);
+    }
+
+    private final T mDefaultValue;
+// AOSP_Comment_Out     private final Supplier<T> mPhenotypeFlag;
+
+// AOSP_Comment_Out     // NOTE: mOverrideValue IS NEVER USED in the non AOSP version.
+    private T mOverrideValue = null;
+    // mOverridden IS NEVER USED in the non AOSP version.
+    private boolean mOverridden = false;
+
+    private ExperimentFlag(
+// AOSP_Comment_Out             Supplier<T> phenotypeFlag,
+            // NOTE: defaultValue IS NEVER USED in the non AOSP version.
+            T defaultValue) {
+        mDefaultValue = defaultValue;
+// AOSP_Comment_Out         mPhenotypeFlag = phenotypeFlag;
+    }
+
+    /** Returns value for this experiment */
+    public T get() {
+        /* Begin_AOSP_Comment_Out
+        if (!BuildConfig.AOSP) {
+            return mPhenotypeFlag.get();
+        }
+        End_AOSP_Comment_Out */
+        return sAllowOverrides && mOverridden ? mOverrideValue : mDefaultValue;
+    }
+
+    @VisibleForTesting
+    public void override(T t) {
+
+        if (sAllowOverrides) {
+            mOverridden = true;
+            mOverrideValue = t;
+        }
+    }
+
+    @VisibleForTesting
+    public void resetOverride() {
+        mOverridden = false;
+    }
+
+    /* Begin_AOSP_Comment_Out
+    @VisibleForTesting
+    T getAospDefaultValueForTesting() {
+        return mDefaultValue;
+    }
+    End_AOSP_Comment_Out */
+}
diff --git a/common/src/com/android/tv/common/experiments/ExperimentLoader.java b/common/src/com/android/tv/common/experiments/ExperimentLoader.java
new file mode 100644
index 0000000..5f012e1
--- /dev/null
+++ b/common/src/com/android/tv/common/experiments/ExperimentLoader.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 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.experiments;
+
+import android.content.Context;
+
+/** Used to sync {@link ExperimentFlag}s. */
+public class ExperimentLoader {
+
+    /** Starts a background task to update {@link ExperimentFlag}s */
+    public void asyncRefreshExperiments(Context context) {
+        // Override for your experiment system
+    }
+}
diff --git a/common/src/com/android/tv/common/experiments/Experiments.java b/common/src/com/android/tv/common/experiments/Experiments.java
new file mode 100644
index 0000000..9bfdb54
--- /dev/null
+++ b/common/src/com/android/tv/common/experiments/Experiments.java
@@ -0,0 +1,64 @@
+/*
+ * 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.common.experiments;
+
+import static com.android.tv.common.experiments.ExperimentFlag.createFlag;
+
+import com.android.tv.common.BuildConfig;
+// AOSP_Comment_Out import com.android.tv.common.flags.LiveChannels;
+
+/**
+ * Set of experiments visible in AOSP.
+ *
+ * <p>This file is maintained by hand.
+ */
+public final class Experiments {
+    public static final ExperimentFlag<Boolean> ENABLE_UNRATED_CONTENT_SETTINGS =
+            ExperimentFlag.createFlag(
+// AOSP_Comment_Out                     LiveChannels::enableUnratedContentSettings,
+                    false);
+
+    /** Turn analytics on or off based on the System Checkbox for logging. */
+    public static final ExperimentFlag<Boolean> ENABLE_ANALYTICS_VIA_CHECKBOX =
+            createFlag(
+// AOSP_Comment_Out                     LiveChannels::enableAnalyticsViaCheckbox,
+                    false);
+
+    /**
+     * Allow developer features such as the dev menu and other aids.
+     *
+     * <p>These features are available to select users(aka fishfooders) on production builds.
+     */
+    public static final ExperimentFlag<Boolean> ENABLE_DEVELOPER_FEATURES =
+            ExperimentFlag.createFlag(
+// AOSP_Comment_Out                     LiveChannels::enableDeveloperFeatures,
+                    BuildConfig.ENG);
+
+    /**
+     * Allow QA features.
+     *
+     * <p>These features must be carefully limited, keeping QA differences to a minimum.
+     *
+     * <p>These features are available to select users(aka QA) on production builds.
+     */
+    public static final ExperimentFlag<Boolean> ENABLE_QA_FEATURES =
+            ExperimentFlag.createFlag(
+// AOSP_Comment_Out                     LiveChannels::enableQaFeatures,
+                    false);
+
+    private Experiments() {}
+}
diff --git a/common/src/com/android/tv/common/feature/CommonFeatures.java b/common/src/com/android/tv/common/feature/CommonFeatures.java
index abe4c1d..04052a7 100644
--- a/common/src/com/android/tv/common/feature/CommonFeatures.java
+++ b/common/src/com/android/tv/common/feature/CommonFeatures.java
@@ -23,14 +23,12 @@
 
 import android.content.Context;
 import android.util.Log;
-
 import com.android.tv.common.flags.has.HasCloudEpgFlags;
 import com.android.tv.common.util.LocationUtils;
-
 import com.android.tv.common.flags.CloudEpgFlags;
 
 /**
- * List of {@link Feature} that affect more than just the TV app.
+ * List of {@link Feature} that affect more than just the Live TV app.
  *
  * <p>Remove the {@code Feature} once it is launched.
  */
@@ -54,7 +52,7 @@
      * <p>Enables dvr recording regardless of storage status.
      */
     public static final Feature FORCE_RECORDING_UNTIL_NO_SPACE =
-            DeveloperPreferenceFeature.create("force_recording_until_no_space", false);
+            PropertyFeature.create("force_recording_until_no_space", false);
 
     /** Show postal code fragment before channel scan. */
     public static final Feature ENABLE_CLOUD_EPG_REGION =
diff --git a/common/src/com/android/tv/common/feature/DeveloperPreferenceFeature.java b/common/src/com/android/tv/common/feature/DeveloperPreferenceFeature.java
deleted file mode 100644
index 1f98547..0000000
--- a/common/src/com/android/tv/common/feature/DeveloperPreferenceFeature.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.tv.common.feature;
-
-import android.content.Context;
-
-import com.android.tv.common.dev.DeveloperPreference;
-
-/** A {@link Feature} based on {@link DeveloperPreference<Boolean>}. */
-public class DeveloperPreferenceFeature implements Feature {
-
-    private final DeveloperPreference<Boolean> mPreference;
-
-    /**
-     * Create a developer preference feature.
-     *
-     * @param key the developer setting key.
-     * @param defaultValue the value to return if the setting is undefined or empty.
-     */
-    public static DeveloperPreferenceFeature create(String key, boolean defaultValue) {
-        return from(DeveloperPreference.create(key, defaultValue));
-    }
-
-    /**
-     * Create a developer preference feature from an exiting {@link DeveloperPreference<Boolean>}.
-     */
-    public static DeveloperPreferenceFeature from(
-            DeveloperPreference<Boolean> developerPreference) {
-        return new DeveloperPreferenceFeature(developerPreference);
-    }
-
-    private DeveloperPreferenceFeature(DeveloperPreference<Boolean> mPreference) {
-        this.mPreference = mPreference;
-    }
-
-    @Override
-    public boolean isEnabled(Context context) {
-        return mPreference.get(context);
-    }
-
-    @Override
-    public String toString() {
-        return mPreference.toString();
-    }
-}
diff --git a/common/src/com/android/tv/common/feature/ExperimentFeature.java b/common/src/com/android/tv/common/feature/ExperimentFeature.java
new file mode 100644
index 0000000..820eda4
--- /dev/null
+++ b/common/src/com/android/tv/common/feature/ExperimentFeature.java
@@ -0,0 +1,44 @@
+/*
+ * 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.common.feature;
+
+import android.content.Context;
+import com.android.tv.common.experiments.ExperimentFlag;
+
+/** A {@link Feature} base on an {@link ExperimentFlag}. */
+public final class ExperimentFeature implements Feature {
+
+    public static Feature from(ExperimentFlag<Boolean> flag) {
+        return new ExperimentFeature(flag);
+    }
+
+    private final ExperimentFlag<Boolean> mFlag;
+
+    private ExperimentFeature(ExperimentFlag<Boolean> flag) {
+        mFlag = flag;
+    }
+
+    @Override
+    public boolean isEnabled(Context context) {
+        return mFlag.get();
+    }
+
+    @Override
+    public String toString() {
+        return "ExperimentFeature for " + mFlag;
+    }
+}
diff --git a/common/src/com/android/tv/common/feature/FeatureUtils.java b/common/src/com/android/tv/common/feature/FeatureUtils.java
index e6192cd..aaed6c8 100644
--- a/common/src/com/android/tv/common/feature/FeatureUtils.java
+++ b/common/src/com/android/tv/common/feature/FeatureUtils.java
@@ -17,6 +17,7 @@
 package com.android.tv.common.feature;
 
 import android.content.Context;
+import com.android.tv.common.BuildConfig;
 import com.android.tv.common.util.CommonUtils;
 import java.util.Arrays;
 
@@ -70,6 +71,23 @@
             }
         };
     }
+    /**
+     * A feature available in AOSP.
+     *
+     * @param googleFeature the feature used in non AOSP builds
+     * @param aospFeature the feature used in AOSP builds
+     */
+    public static Feature aospFeature(
+// AOSP_Comment_Out             final Feature googleFeature,
+            final Feature aospFeature) {
+        /* Begin_AOSP_Comment_Out
+        if (!BuildConfig.AOSP) {
+            return googleFeature;
+        } else {
+            End_AOSP_Comment_Out */
+            return aospFeature;
+// AOSP_Comment_Out         }
+    }
 
     /**
      * Returns a feature that is opposite of the given {@code feature}.
diff --git a/common/src/com/android/tv/common/feature/Model.java b/common/src/com/android/tv/common/feature/Model.java
index 450cd21..7aa5148 100644
--- a/common/src/com/android/tv/common/feature/Model.java
+++ b/common/src/com/android/tv/common/feature/Model.java
@@ -21,11 +21,10 @@
 /** Holder for {@link android.os.Build#MODEL} features. */
 public interface Model {
 
-    ModelFeature ARCHER = new ModelFeature("Archer");
     ModelFeature NEXUS_PLAYER = new ModelFeature("Nexus Player");
 
     /** True when the {@link android.os.Build#MODEL} equals the {@code model} given. */
-    final class ModelFeature implements Feature {
+    public static final class ModelFeature implements Feature {
         private final String mModel;
 
         private ModelFeature(String model) {
diff --git a/common/src/com/android/tv/common/feature/PermissionFeature.java b/common/src/com/android/tv/common/feature/PermissionFeature.java
deleted file mode 100644
index 0261178..0000000
--- a/common/src/com/android/tv/common/feature/PermissionFeature.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.tv.common.feature;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-
-/** A feature that is only available when {@code permissionName} is granted. */
-public class PermissionFeature implements Feature {
-
-    public static final PermissionFeature DVB_DEVICE_PERMISSION =
-            new PermissionFeature("android.permission.DVB_DEVICE");
-
-    private final String permissionName;
-
-    private PermissionFeature(String permissionName) {
-        this.permissionName = permissionName;
-    }
-
-    @Override
-    public boolean isEnabled(Context context) {
-        return context.checkSelfPermission(permissionName) == PackageManager.PERMISSION_GRANTED;
-    }
-}
diff --git a/common/src/com/android/tv/common/feature/Sdk.java b/common/src/com/android/tv/common/feature/Sdk.java
index 54bc1bb..4b0a925 100644
--- a/common/src/com/android/tv/common/feature/Sdk.java
+++ b/common/src/com/android/tv/common/feature/Sdk.java
@@ -29,6 +29,8 @@
 
     public static final Feature AT_LEAST_O = new AtLeast(VERSION_CODES.O);
 
+    public static final Feature AT_LEAST_P = new AtLeast(VERSION_CODES.P); // AOSP_OC:strip_line
+
     private static final class AtLeast implements Feature {
 
         private final int versionCode;
diff --git a/common/src/com/android/tv/common/flags/BackendKnobsFlags.java b/common/src/com/android/tv/common/flags/BackendKnobsFlags.java
index 3b65df5..69bac7a 100644
--- a/common/src/com/android/tv/common/flags/BackendKnobsFlags.java
+++ b/common/src/com/android/tv/common/flags/BackendKnobsFlags.java
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License
  */
-
 package com.android.tv.common.flags;
 
 /** Flags for tuning non ui behavior */
@@ -27,8 +26,8 @@
      */
     boolean compiled();
 
-    /** Number of channels to batch together when fetching programs */
-    long epgFetcherChannelsPerProgramFetch();
+    /** Enable fetching only part of the program data. */
+    boolean enablePartialProgramFetch();
 
     /** EPG fetcher interval in hours */
     long epgFetcherIntervalHour();
@@ -36,6 +35,9 @@
     /** Target channel count for EPG. It is used to adjust the EPG length */
     long epgTargetChannelCount();
 
+    /** Enables fetching a few hours of programs only when the epg is scrolled to that time. */
+    boolean fetchProgramsAsNeeded();
+
     /** How many hours of programs are loaded in the program guide for during the initial fetch */
     long programGuideInitialFetchHours();
 
diff --git a/common/src/com/android/tv/common/flags/CloudEpgFlags.java b/common/src/com/android/tv/common/flags/CloudEpgFlags.java
index db2789c..ab4c6a1 100755
--- a/common/src/com/android/tv/common/flags/CloudEpgFlags.java
+++ b/common/src/com/android/tv/common/flags/CloudEpgFlags.java
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License
  */
-
 package com.android.tv.common.flags;
 
 /** Flags for Cloud EPG */
@@ -30,6 +29,6 @@
     /** Is the device in a region supported by Cloud Epg */
     boolean supportedRegion();
 
-    /** List of input ids that the TV app will update their EPG. */
+    /** List of input ids that Live TV will update their EPG. */
     String thirdPartyEpgInputsCsv();
 }
diff --git a/common/src/com/android/tv/common/flags/DvrFlags.java b/common/src/com/android/tv/common/flags/ConcurrentDvrPlaybackFlags.java
similarity index 76%
rename from common/src/com/android/tv/common/flags/DvrFlags.java
rename to common/src/com/android/tv/common/flags/ConcurrentDvrPlaybackFlags.java
index 9deae1f..1afff79 100755
--- a/common/src/com/android/tv/common/flags/DvrFlags.java
+++ b/common/src/com/android/tv/common/flags/ConcurrentDvrPlaybackFlags.java
@@ -13,11 +13,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License
  */
-
 package com.android.tv.common.flags;
 
-/** DVR flags */
-public interface DvrFlags {
+/** Flags allowing concurrent DVR playback */
+public interface ConcurrentDvrPlaybackFlags {
 
     /**
      * Whether or not this feature is compiled into this build.
@@ -27,9 +26,9 @@
      */
     boolean compiled();
 
-    /** Allow user to customize timings of program recordings. */
-    boolean startEarlyEndLateEnabled();
+    /** Enable playback of DVR playback during recording */
+    boolean enabled();
 
-    /** Store and use the video aspect ratio in recordings. */
-    boolean storeVideoAspectRatio();
+    /** Enable tuner using recording data for playback in onTune */
+    boolean onTuneUsesRecording();
 }
diff --git a/common/src/com/android/tv/common/flags/LegacyFlags.java b/common/src/com/android/tv/common/flags/LegacyFlags.java
deleted file mode 100755
index d0cb1e4..0000000
--- a/common/src/com/android/tv/common/flags/LegacyFlags.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2019 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.flags;
-
-/** Legacy flags */
-public interface LegacyFlags {
-
-    /**
-     * Whether or not this feature is compiled into this build.
-     *
-     * <p>This returns true by default, unless the is_compiled_selector parameter was set during
-     * code generation.
-     */
-    boolean compiled();
-
-    /** Enable Developer Features */
-    boolean enableDeveloperFeatures();
-
-    /** Enable QA Features */
-    boolean enableQaFeatures();
-
-    /** Enable Unrated Content Settings */
-    boolean enableUnratedContentSettings();
-}
diff --git a/common/src/com/android/tv/common/flags/MessagesFlags.java b/common/src/com/android/tv/common/flags/MessagesFlags.java
deleted file mode 100755
index 596442f..0000000
--- a/common/src/com/android/tv/common/flags/MessagesFlags.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2019 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.flags;
-
-/**
- * Message flags.
- *
- * <p>Used to hide new messages until all translations are ready.
- *
- * <p>Production releases never include the messages protected by these flags.
- */
-public interface MessagesFlags {
-
-    /**
-     * Whether or not this feature is compiled into this build.
-     *
-     * <p>This returns true by default, unless the is_compiled_selector parameter was set during
-     * code generation.
-     */
-    boolean compiled();
-}
diff --git a/common/src/com/android/tv/common/flags/SetupFlags.java b/common/src/com/android/tv/common/flags/SetupFlags.java
deleted file mode 100755
index 0a7f200..0000000
--- a/common/src/com/android/tv/common/flags/SetupFlags.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2019 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.flags;
-
-/** Flags for changing setup behavior */
-public interface SetupFlags {
-
-    /**
-     * Whether or not this feature is compiled into this build.
-     *
-     * <p>This returns true by default, unless the is_compiled_selector parameter was set during
-     * code generation.
-     */
-    boolean compiled();
-
-    /** Packages allowed to send intents to SetupPassthroughActivity. */
-    com.android.tv.common.flags.proto.TypedFeatures.StringListParam
-            setupPassThroughPackageWhitelist();
-
-    /** Use a whitelist for packages allowed to start SetupPassthroughActivity */
-    boolean useWhitelistForSetupPassThrough();
-}
diff --git a/common/src/com/android/tv/common/flags/StartupFlags.java b/common/src/com/android/tv/common/flags/StartupFlags.java
deleted file mode 100755
index 2f64c9f..0000000
--- a/common/src/com/android/tv/common/flags/StartupFlags.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2019 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.flags;
-
-/** Flags for TV App startup */
-public interface StartupFlags {
-
-    /**
-     * Whether or not this feature is compiled into this build.
-     *
-     * <p>This returns true by default, unless the is_compiled_selector parameter was set during
-     * code generation.
-     */
-    boolean compiled();
-
-    /** InputId's that will not be warmed up on MainActivity creation. */
-    com.android.tv.common.flags.proto.TypedFeatures.StringListParam warmupInputidBlacklist();
-}
diff --git a/common/src/com/android/tv/common/flags/TunerFlags.java b/common/src/com/android/tv/common/flags/TunerFlags.java
index 5ecfb5b..5f899b9 100755
--- a/common/src/com/android/tv/common/flags/TunerFlags.java
+++ b/common/src/com/android/tv/common/flags/TunerFlags.java
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License
  */
-
 package com.android.tv.common.flags;
 
 /** Flags for tuner */
@@ -27,6 +26,9 @@
      */
     boolean compiled();
 
+    /** Tune using current recording if available. */
+    boolean tuneUsingRecording();
+
     /** Enable using exoplayer V2 */
     boolean useExoplayerV2();
 }
diff --git a/common/src/com/android/tv/common/flags/UiFlags.java b/common/src/com/android/tv/common/flags/UiFlags.java
index 2bd8a59..4c88d08 100755
--- a/common/src/com/android/tv/common/flags/UiFlags.java
+++ b/common/src/com/android/tv/common/flags/UiFlags.java
@@ -13,10 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License
  */
-
 package com.android.tv.common.flags;
 
-/** Flags for TV app UI */
+/** Flags for Live TV UI */
 public interface UiFlags {
 
     /**
@@ -27,9 +26,6 @@
      */
     boolean compiled();
 
-    /** Critic Ratings */
-    boolean enableCriticRatings();
-
     /**
      * Number of days to be shown by Recording History.
      *
@@ -38,5 +34,8 @@
     long maxHistoryDays();
 
     /** Unhide the launcher all the time */
-    boolean unhideLauncher();
+    boolean uhideLauncher();
+
+    /** Use the Leanback Pin Picker */
+    boolean useLeanbackPinPicker();
 }
diff --git a/common/src/com/android/tv/common/flags/has/HasConcurrentDvrPlaybackFlags.java b/common/src/com/android/tv/common/flags/has/HasConcurrentDvrPlaybackFlags.java
new file mode 100644
index 0000000..b471087
--- /dev/null
+++ b/common/src/com/android/tv/common/flags/has/HasConcurrentDvrPlaybackFlags.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2018 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.flags.has;
+
+import android.content.Context;
+import com.android.tv.common.flags.ConcurrentDvrPlaybackFlags;
+
+/** Has {@link ConcurrentDvrPlaybackFlags} */
+public interface HasConcurrentDvrPlaybackFlags {
+
+    static ConcurrentDvrPlaybackFlags fromContext(Context context) {
+        return ((HasConcurrentDvrPlaybackFlags) HasUtils.getApplicationContext(context))
+                .getConcurrentDvrPlaybackFlags();
+    }
+
+    ConcurrentDvrPlaybackFlags getConcurrentDvrPlaybackFlags();
+}
diff --git a/common/src/com/android/tv/common/flags/impl/DefaultBackendKnobsFlags.java b/common/src/com/android/tv/common/flags/impl/DefaultBackendKnobsFlags.java
index 5302842..a189e47 100644
--- a/common/src/com/android/tv/common/flags/impl/DefaultBackendKnobsFlags.java
+++ b/common/src/com/android/tv/common/flags/impl/DefaultBackendKnobsFlags.java
@@ -25,8 +25,8 @@
     }
 
     @Override
-    public long epgFetcherChannelsPerProgramFetch() {
-        return 50;
+    public boolean enablePartialProgramFetch() {
+        return false;
     }
 
     @Override
@@ -35,8 +35,13 @@
     }
 
     @Override
+    public boolean fetchProgramsAsNeeded() {
+        return false;
+    }
+
+    @Override
     public long programGuideInitialFetchHours() {
-        return 4;
+        return 8;
     }
 
     @Override
diff --git a/common/src/com/android/tv/common/flags/impl/DefaultDvrFlags.java b/common/src/com/android/tv/common/flags/impl/DefaultConcurrentDvrPlaybackFlags.java
similarity index 74%
rename from common/src/com/android/tv/common/flags/impl/DefaultDvrFlags.java
rename to common/src/com/android/tv/common/flags/impl/DefaultConcurrentDvrPlaybackFlags.java
index 09f7b4f..8d8c584 100644
--- a/common/src/com/android/tv/common/flags/impl/DefaultDvrFlags.java
+++ b/common/src/com/android/tv/common/flags/impl/DefaultConcurrentDvrPlaybackFlags.java
@@ -15,9 +15,10 @@
  */
 package com.android.tv.common.flags.impl;
 
-/** Flags for tuning non ui behavior. */
-public final class DefaultDvrFlags
-        implements com.android.tv.common.flags.DvrFlags {
+import com.android.tv.common.flags.ConcurrentDvrPlaybackFlags;
+
+/** Default flags for Concurrent DVR Playback */
+public final class DefaultConcurrentDvrPlaybackFlags implements ConcurrentDvrPlaybackFlags {
 
     @Override
     public boolean compiled() {
@@ -25,12 +26,12 @@
     }
 
     @Override
-    public boolean startEarlyEndLateEnabled() {
+    public boolean enabled() {
         return false;
     }
 
     @Override
-    public boolean storeVideoAspectRatio() {
+    public boolean onTuneUsesRecording() {
         return false;
     }
 }
diff --git a/common/src/com/android/tv/common/flags/impl/DefaultFlagsModule.java b/common/src/com/android/tv/common/flags/impl/DefaultFlagsModule.java
index 10be34b..4935236 100644
--- a/common/src/com/android/tv/common/flags/impl/DefaultFlagsModule.java
+++ b/common/src/com/android/tv/common/flags/impl/DefaultFlagsModule.java
@@ -18,12 +18,9 @@
 import dagger.Module;
 import dagger.Provides;
 import dagger.Reusable;
-
 import com.android.tv.common.flags.BackendKnobsFlags;
 import com.android.tv.common.flags.CloudEpgFlags;
-import com.android.tv.common.flags.DvrFlags;
-import com.android.tv.common.flags.LegacyFlags;
-import com.android.tv.common.flags.StartupFlags;
+import com.android.tv.common.flags.ConcurrentDvrPlaybackFlags;
 import com.android.tv.common.flags.TunerFlags;
 import com.android.tv.common.flags.UiFlags;
 
@@ -45,20 +42,8 @@
 
     @Provides
     @Reusable
-    DvrFlags provideDvrFlags() {
-        return new DefaultDvrFlags();
-    }
-
-    @Provides
-    @Reusable
-    LegacyFlags provideLegacyFlags() {
-        return DefaultLegacyFlags.DEFAULT;
-    }
-
-    @Provides
-    @Reusable
-    StartupFlags provideStartupFlags() {
-        return new DefaultStartupFlags();
+    ConcurrentDvrPlaybackFlags provideConcurrentDvrPlaybackFlags() {
+        return new DefaultConcurrentDvrPlaybackFlags();
     }
 
     @Provides
diff --git a/common/src/com/android/tv/common/flags/impl/DefaultLegacyFlags.java b/common/src/com/android/tv/common/flags/impl/DefaultLegacyFlags.java
deleted file mode 100644
index 5214241..0000000
--- a/common/src/com/android/tv/common/flags/impl/DefaultLegacyFlags.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2019 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.flags.impl;
-
-import com.google.auto.value.AutoValue;
-import com.android.tv.common.flags.LegacyFlags;
-
-/** Default {@link LegacyFlags}. */
-@AutoValue
-public abstract class DefaultLegacyFlags implements LegacyFlags {
-    public static final DefaultLegacyFlags DEFAULT = DefaultLegacyFlags.builder().build();
-
-    public static Builder builder() {
-        return new AutoValue_DefaultLegacyFlags.Builder()
-                .compiled(true)
-                .enableDeveloperFeatures(false)
-                .enableQaFeatures(false)
-                .enableUnratedContentSettings(false);
-    }
-
-    /** Builder for {@link LegacyFlags} */
-    @AutoValue.Builder
-    public abstract static class Builder {
-        public abstract Builder compiled(boolean value);
-
-        public abstract Builder enableDeveloperFeatures(boolean value);
-
-        public abstract Builder enableQaFeatures(boolean value);
-
-        public abstract Builder enableUnratedContentSettings(boolean value);
-
-        public abstract DefaultLegacyFlags build();
-    }
-}
diff --git a/common/src/com/android/tv/common/flags/impl/DefaultMessagesFlags.java b/common/src/com/android/tv/common/flags/impl/DefaultMessagesFlags.java
deleted file mode 100644
index f2130a3..0000000
--- a/common/src/com/android/tv/common/flags/impl/DefaultMessagesFlags.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2019 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.flags.impl;
-
-/**
- * Default flag values for {@link
- * com.android.tv.common.flags.MessagesFlags}.
- */
-public final class DefaultMessagesFlags
-        implements com.android.tv.common.flags.MessagesFlags {
-
-    @Override
-    public boolean compiled() {
-        return true;
-    }
-
-}
diff --git a/common/src/com/android/tv/common/flags/impl/DefaultSetupFlags.java b/common/src/com/android/tv/common/flags/impl/DefaultSetupFlags.java
deleted file mode 100644
index 3abe662..0000000
--- a/common/src/com/android/tv/common/flags/impl/DefaultSetupFlags.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2019 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.flags.impl;
-
-import com.android.tv.common.flags.proto.TypedFeatures.StringListParam;
-
-import com.android.tv.common.flags.SetupFlags;
-
-/** Default {@link SetupFlags} */
-public class DefaultSetupFlags implements SetupFlags {
-    @Override
-    public boolean compiled() {
-        return true;
-    }
-
-    @Override
-    public StringListParam setupPassThroughPackageWhitelist() {
-        return StringListParam.getDefaultInstance();
-    }
-
-    @Override
-    public boolean useWhitelistForSetupPassThrough() {
-        return false;
-    }
-}
diff --git a/common/src/com/android/tv/common/flags/impl/DefaultStartupFlags.java b/common/src/com/android/tv/common/flags/impl/DefaultStartupFlags.java
deleted file mode 100644
index 3eb6edc..0000000
--- a/common/src/com/android/tv/common/flags/impl/DefaultStartupFlags.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2019 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.flags.impl;
-
-import com.android.tv.common.flags.proto.TypedFeatures.StringListParam;
-import com.android.tv.common.flags.StartupFlags;
-
-/** Default {@link StartupFlags} */
-public class DefaultStartupFlags implements StartupFlags {
-    @Override
-    public boolean compiled() {
-        return true;
-    }
-
-    @Override
-    public StringListParam warmupInputidBlacklist() {
-        return StringListParam.getDefaultInstance();
-    }
-}
diff --git a/common/src/com/android/tv/common/flags/impl/DefaultTunerFlags.java b/common/src/com/android/tv/common/flags/impl/DefaultTunerFlags.java
index 2d12e36..195953b 100644
--- a/common/src/com/android/tv/common/flags/impl/DefaultTunerFlags.java
+++ b/common/src/com/android/tv/common/flags/impl/DefaultTunerFlags.java
@@ -26,6 +26,11 @@
     }
 
     @Override
+    public boolean tuneUsingRecording() {
+        return false;
+    }
+
+    @Override
     public boolean useExoplayerV2() {
         return false;
     }
diff --git a/common/src/com/android/tv/common/flags/impl/DefaultUiFlags.java b/common/src/com/android/tv/common/flags/impl/DefaultUiFlags.java
index 43f0dea..fce4585 100644
--- a/common/src/com/android/tv/common/flags/impl/DefaultUiFlags.java
+++ b/common/src/com/android/tv/common/flags/impl/DefaultUiFlags.java
@@ -17,7 +17,7 @@
 
 import com.android.tv.common.flags.UiFlags;
 
-/** Default Flags for TV app UI */
+/** Default Flags for Live TV UI */
 public class DefaultUiFlags implements UiFlags {
 
     @Override
@@ -26,17 +26,17 @@
     }
 
     @Override
-    public boolean enableCriticRatings() {
+    public boolean uhideLauncher() {
         return false;
     }
 
     @Override
-    public boolean unhideLauncher() {
+    public boolean useLeanbackPinPicker() {
         return false;
     }
 
     @Override
     public long maxHistoryDays() {
-        return 0;
+        return 7;
     }
 }
diff --git a/common/src/com/android/tv/common/flags/impl/SettableFlagsModule.java b/common/src/com/android/tv/common/flags/impl/SettableFlagsModule.java
deleted file mode 100644
index ab4ebd3..0000000
--- a/common/src/com/android/tv/common/flags/impl/SettableFlagsModule.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2019 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.flags.impl;
-
-import dagger.Module;
-import dagger.Provides;
-import dagger.Reusable;
-
-import com.android.tv.common.flags.BackendKnobsFlags;
-import com.android.tv.common.flags.CloudEpgFlags;
-import com.android.tv.common.flags.DvrFlags;
-import com.android.tv.common.flags.LegacyFlags;
-import com.android.tv.common.flags.SetupFlags;
-import com.android.tv.common.flags.StartupFlags;
-import com.android.tv.common.flags.TunerFlags;
-import com.android.tv.common.flags.UiFlags;
-
-/** Provides public fields for each flag so they can be changed before injection. */
-@Module
-public class SettableFlagsModule {
-
-    public DefaultBackendKnobsFlags backendKnobsFlags = new DefaultBackendKnobsFlags();
-    public DefaultCloudEpgFlags cloudEpgFlags = new DefaultCloudEpgFlags();
-    public DefaultDvrFlags dvrFlags = new DefaultDvrFlags();
-    public DefaultLegacyFlags legacyFlags = DefaultLegacyFlags.DEFAULT;
-    public DefaultSetupFlags setupFlags = new DefaultSetupFlags();
-    public DefaultStartupFlags startupFlags = new DefaultStartupFlags();
-    public DefaultTunerFlags tunerFlags = new DefaultTunerFlags();
-    public DefaultUiFlags uiFlags = new DefaultUiFlags();
-
-    @Provides
-    @Reusable
-    BackendKnobsFlags provideBackendKnobsFlags() {
-        return backendKnobsFlags;
-    }
-
-    @Provides
-    @Reusable
-    CloudEpgFlags provideCloudEpgFlags() {
-        return cloudEpgFlags;
-    }
-
-    @Provides
-    @Reusable
-    DvrFlags provideDvrFlags() {
-        return dvrFlags;
-    }
-
-    @Provides
-    @Reusable
-    LegacyFlags provideLegacyFlags() {
-        return legacyFlags;
-    }
-
-    @Provides
-    @Reusable
-    SetupFlags provideSetupFlags() {
-        return setupFlags;
-    }
-
-    @Provides
-    @Reusable
-    StartupFlags provideStartupFlags() {
-        return startupFlags;
-    }
-
-    @Provides
-    @Reusable
-    TunerFlags provideTunerFlags() {
-        return tunerFlags;
-    }
-
-    @Provides
-    @Reusable
-    UiFlags provideUiFlags() {
-        return uiFlags;
-    }
-}
diff --git a/common/src/com/android/tv/common/flags/proto/typed-features.proto b/common/src/com/android/tv/common/flags/proto/typed-features.proto
deleted file mode 100644
index 855d731..0000000
--- a/common/src/com/android/tv/common/flags/proto/typed-features.proto
+++ /dev/null
@@ -1,20 +0,0 @@
-syntax = "proto2";
-
-package android.tv.common.flags;
-
-option java_outer_classname = "TypedFeatures";
-option java_package = "com.android.tv.common.flags.proto";
-
-// These messages are to specify feature params that are a list of integers.
-message Int32ListParam {
-  repeated int32 element = 1;
-}
-
-message Int64ListParam {
-  repeated int64 element = 1;
-}
-
-// This message is to specify feature params that are a list of strings.
-message StringListParam {
-  repeated string element = 1;
-}
diff --git a/common/src/com/android/tv/common/recording/RecordingStorageStatusManager.java b/common/src/com/android/tv/common/recording/RecordingStorageStatusManager.java
index 3552a66..0fb864b 100644
--- a/common/src/com/android/tv/common/recording/RecordingStorageStatusManager.java
+++ b/common/src/com/android/tv/common/recording/RecordingStorageStatusManager.java
@@ -28,11 +28,8 @@
 import android.support.annotation.IntDef;
 import android.support.annotation.WorkerThread;
 import android.util.Log;
-
 import com.android.tv.common.SoftPreconditions;
-import com.android.tv.common.dagger.annotations.ApplicationContext;
 import com.android.tv.common.feature.CommonFeatures;
-
 import java.io.File;
 import java.io.IOException;
 import java.lang.annotation.Retention;
@@ -41,13 +38,10 @@
 import java.util.Set;
 import java.util.concurrent.CopyOnWriteArraySet;
 
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
 /** Signals DVR storage status change such as plugging/unplugging. */
-@Singleton
 public class RecordingStorageStatusManager {
     private static final String TAG = "RecordingStorageStatusManager";
+    private static final boolean DEBUG = false;
 
     /** Minimum storage size to support DVR */
     public static final long MIN_STORAGE_SIZE_FOR_DVR_IN_BYTES = 50 * 1024 * 1024 * 1024L; // 50GB
@@ -149,8 +143,7 @@
      *
      * @param context {@link Context}
      */
-    @Inject
-    public RecordingStorageStatusManager(@ApplicationContext Context context) {
+    public RecordingStorageStatusManager(final Context context) {
         mContext = context;
         mMountedStorageStatus = getStorageStatusInternal();
         mStorageValid = mMountedStorageStatus.isValidForDvr();
diff --git a/common/src/com/android/tv/common/singletons/HasTvInputId.java b/common/src/com/android/tv/common/singletons/HasTvInputId.java
index 49cf3d2..4bc0a21 100644
--- a/common/src/com/android/tv/common/singletons/HasTvInputId.java
+++ b/common/src/com/android/tv/common/singletons/HasTvInputId.java
@@ -18,8 +18,8 @@
 /**
  * Has TunerInputId.
  *
- * <p>This is used buy both the tuner to get its input id and by the TV app to get the embedded
- * tuner input id.
+ * <p>This is used buy both the tuner to get its input id and by the Live TV to get the
+ * embedded tuner input id.
  */
 public interface HasTvInputId {
 
diff --git a/common/src/com/android/tv/common/support/tvprovider/README.md b/common/src/com/android/tv/common/support/tvprovider/README.md
deleted file mode 100644
index a24dc28..0000000
--- a/common/src/com/android/tv/common/support/tvprovider/README.md
+++ /dev/null
@@ -1,6 +0,0 @@
-## support provider
-
-This is preview code destined to be put in androidx.tvprovider.media.tv
-
-
-All classes here must have an associated bug to move to androidx
diff --git a/common/src/com/android/tv/common/support/tvprovider/TvContractCompatX.java b/common/src/com/android/tv/common/support/tvprovider/TvContractCompatX.java
deleted file mode 100644
index 353e342..0000000
--- a/common/src/com/android/tv/common/support/tvprovider/TvContractCompatX.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2019 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.support.tvprovider;
-
-import android.net.Uri;
-import android.support.annotation.Nullable;
-import androidx.tvprovider.media.tv.TvContractCompat;
-
-/**
- * Extensions to the contract between the TV provider and applications. Contains definitions for the
- * supported URIs and columns.
- *
- * <p>TODO(b/126921088): move this to androidx.
- */
-public final class TvContractCompatX {
-
-    /**
-     * Builds a URI that points to a specific channel.
-     *
-     * @param inputPackage the package of the input.
-     * @param internalProviderId the internal provider id
-     */
-    public static Uri buildChannelUri(
-            @Nullable String inputPackage, @Nullable String internalProviderId) {
-        Uri.Builder uri = TvContractCompat.Channels.CONTENT_URI.buildUpon();
-        if (inputPackage != null) {
-            uri.appendQueryParameter("package", inputPackage);
-        }
-        if (internalProviderId != null) {
-            uri.appendQueryParameter(
-                    TvContractCompat.Channels.COLUMN_INTERNAL_PROVIDER_ID, internalProviderId);
-        }
-        return uri.build();
-    }
-
-    /**
-     * Builds a URI that points to all programs on a given channel.
-     *
-     * @param inputPackage the package of the input.
-     * @param internalProviderId the internal provider id
-     */
-    public static Uri buildProgramsUriForChannel(
-            @Nullable String inputPackage, @Nullable String internalProviderId) {
-        Uri.Builder uri = TvContractCompat.Programs.CONTENT_URI.buildUpon();
-        if (inputPackage != null) {
-            uri.appendQueryParameter("package", inputPackage);
-        }
-        if (internalProviderId != null) {
-            uri.appendQueryParameter(
-                    TvContractCompat.Channels.COLUMN_INTERNAL_PROVIDER_ID, internalProviderId);
-        }
-        return uri.build();
-    }
-
-    /**
-     * Builds a URI that points to programs on a specific channel whose schedules overlap with the
-     * given time frame.
-     *
-     * @param inputPackage the package of the input.
-     * @param internalProviderId the internal provider id
-     * @param startTime The start time used to filter programs. The returned programs should have
-     *     {@link TvContractCompat.Programs#COLUMN_END_TIME_UTC_MILLIS} that is greater than this
-     *     time.
-     * @param endTime The end time used to filter programs. The returned programs should have {@link
-     *     TvContractCompat.Programs#COLUMN_START_TIME_UTC_MILLIS} that is less than this time.
-     */
-    public static Uri buildProgramsUriForChannel(
-            @Nullable String inputPackage,
-            @Nullable String internalProviderId,
-            long startTime,
-            long endTime) {
-        return buildProgramsUriForChannel(inputPackage, internalProviderId)
-                .buildUpon()
-                .appendQueryParameter(TvContractCompat.PARAM_START_TIME, String.valueOf(startTime))
-                .appendQueryParameter(TvContractCompat.PARAM_END_TIME, String.valueOf(endTime))
-                .build();
-    }
-
-    /**
-     * Builds a URI that points to programs whose schedules overlap with the given time frame.
-     *
-     * @param startTime The start time used to filter programs. The returned programs should have
-     *     {@link TvContractCompat.Programs#COLUMN_END_TIME_UTC_MILLIS} that is greater than this
-     *     time.
-     * @param endTime The end time used to filter programs. The returned programs should have {@link
-     *     TvContractCompat.Programs#COLUMN_START_TIME_UTC_MILLIS} that is less than this time.
-     */
-    public static Uri buildProgramsUri(long startTime, long endTime) {
-        return TvContractCompat.Programs.CONTENT_URI
-                .buildUpon()
-                .appendQueryParameter(TvContractCompat.PARAM_START_TIME, String.valueOf(startTime))
-                .appendQueryParameter(TvContractCompat.PARAM_END_TIME, String.valueOf(endTime))
-                .build();
-    }
-}
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 2a6ceec..3c76c26 100644
--- a/common/src/com/android/tv/common/ui/setup/SetupGuidedStepFragment.java
+++ b/common/src/com/android/tv/common/ui/setup/SetupGuidedStepFragment.java
@@ -19,11 +19,11 @@
 import static android.content.Context.ACCESSIBILITY_SERVICE;
 
 import android.os.Bundle;
-import androidx.leanback.app.GuidedStepFragment;
-import androidx.leanback.widget.GuidanceStylist;
-import androidx.leanback.widget.GuidedAction;
-import androidx.leanback.widget.GuidedActionsStylist;
-import androidx.leanback.widget.VerticalGridView;
+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.GuidedActionsStylist;
+import android.support.v17.leanback.widget.VerticalGridView;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.AccessibilityDelegate;
@@ -53,9 +53,9 @@
             LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
         View view = super.onCreateView(inflater, container, savedInstanceState);
         Bundle arguments = getArguments();
-        view.findViewById(androidx.leanback.R.id.action_fragment_root)
+        view.findViewById(android.support.v17.leanback.R.id.action_fragment_root)
                 .setPadding(0, 0, 0, 0);
-        mContentFragment = view.findViewById(androidx.leanback.R.id.content_fragment);
+        mContentFragment = view.findViewById(android.support.v17.leanback.R.id.content_fragment);
         LinearLayout.LayoutParams guidanceLayoutParams =
                 (LinearLayout.LayoutParams) mContentFragment.getLayoutParams();
         guidanceLayoutParams.weight = 0;
@@ -69,7 +69,7 @@
                     getResources()
                             .getDimensionPixelOffset(R.dimen.setup_done_button_container_width);
             // Guided actions list
-            View list = view.findViewById(androidx.leanback.R.id.guidedactions_list);
+            View list = view.findViewById(android.support.v17.leanback.R.id.guidedactions_list);
             MarginLayoutParams marginLayoutParams = (MarginLayoutParams) list.getLayoutParams();
             // Use content view to check layout direction while view is being created.
             if (getResources().getConfiguration().getLayoutDirection()
@@ -93,12 +93,12 @@
         gridView.setWindowAlignmentOffset(offset);
         gridView.setWindowAlignmentOffsetPercent(0);
         gridView.setItemAlignmentOffsetPercent(0);
-        ((ViewGroup) view.findViewById(androidx.leanback.R.id.guidedactions_list))
+        ((ViewGroup) view.findViewById(android.support.v17.leanback.R.id.guidedactions_list))
                 .setTransitionGroup(false);
         // Needed for the shared element transition.
         // content_frame is defined in leanback.
         ViewGroup group =
-                (ViewGroup) view.findViewById(androidx.leanback.R.id.content_frame);
+                (ViewGroup) view.findViewById(android.support.v17.leanback.R.id.content_frame);
         group.setClipChildren(false);
         group.setClipToPadding(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 ee00e9f..c02d3f5 100644
--- a/common/src/com/android/tv/common/ui/setup/SetupMultiPaneFragment.java
+++ b/common/src/com/android/tv/common/ui/setup/SetupMultiPaneFragment.java
@@ -112,15 +112,15 @@
     @Override
     protected int[] getParentIdsForDelay() {
         return new int[] {
-            androidx.leanback.R.id.content_fragment,
-            androidx.leanback.R.id.guidedactions_list
+            android.support.v17.leanback.R.id.content_fragment,
+            android.support.v17.leanback.R.id.guidedactions_list
         };
     }
 
     @Override
     public int[] getSharedElementIds() {
         return new int[] {
-            androidx.leanback.R.id.action_fragment_background, R.id.done_button_container
+            android.support.v17.leanback.R.id.action_fragment_background, R.id.done_button_container
         };
     }
 }
diff --git a/common/src/com/android/tv/common/ui/setup/animation/TranslationAnimationCreator.java b/common/src/com/android/tv/common/ui/setup/animation/TranslationAnimationCreator.java
index 5970693..13b89ea 100644
--- a/common/src/com/android/tv/common/ui/setup/animation/TranslationAnimationCreator.java
+++ b/common/src/com/android/tv/common/ui/setup/animation/TranslationAnimationCreator.java
@@ -20,7 +20,7 @@
 import android.animation.ObjectAnimator;
 import android.animation.TimeInterpolator;
 import android.graphics.Path;
-import androidx.leanback.R;
+import android.support.v17.leanback.R;
 import android.transition.Transition;
 import android.transition.TransitionValues;
 import android.view.View;
@@ -29,9 +29,9 @@
  * This class is used by Slide and Explode to create an animator that goes from the start position
  * to the end position. It takes into account the canceled position so that it will not blink out or
  * shift suddenly when the transition is interrupted. The original class is
- * androidx.leanback.transition.TranslationAnimationCreator which is hidden.
+ * android.support.v17.leanback.transition.TranslationAnimationCreator which is hidden.
  */
-// Copied from androidx.leanback.transition.TransltaionAnimationCreator
+// Copied from android.support.v17.leanback.transition.TransltaionAnimationCreator
 class TranslationAnimationCreator {
     /**
      * Creates an animator that can be used for x and/or y translations. When interrupted, it sets a
diff --git a/common/src/com/android/tv/common/util/CommonUtils.java b/common/src/com/android/tv/common/util/CommonUtils.java
index 662f819..4513a87 100644
--- a/common/src/com/android/tv/common/util/CommonUtils.java
+++ b/common/src/com/android/tv/common/util/CommonUtils.java
@@ -22,8 +22,10 @@
 import android.os.Build;
 import android.util.ArraySet;
 import android.util.Log;
+import com.android.tv.common.BuildConfig;
 import com.android.tv.common.CommonConstants;
 import com.android.tv.common.actions.InputSetupActionUtils;
+import com.android.tv.common.experiments.Experiments;
 import java.io.File;
 import java.text.SimpleDateFormat;
 import java.util.Date;
@@ -51,7 +53,6 @@
 
     static {
         BUNDLED_PACKAGE_SET.add("com.android.tv");
-// AOSP_Comment_Out         BUNDLED_PACKAGE_SET.add(CommonConstants.BASE_PACKAGE);
     }
 
     private static Boolean sRunningInTest;
@@ -122,11 +123,16 @@
         return false;
     }
 
-    /** Returns true if the application is packaged with TV app. */
+    /** Returns true if the application is packaged with Live TV. */
     public static boolean isPackagedWithLiveChannels(Context context) {
         return (CommonConstants.BASE_PACKAGE.equals(context.getPackageName()));
     }
 
+    /** Returns true if the current user is a developer. */
+    public static boolean isDeveloper() {
+        return BuildConfig.ENG || Experiments.ENABLE_DEVELOPER_FEATURES.get();
+    }
+
     /** Converts time in milliseconds to a ISO 8061 string. */
     public static String toIsoDateTimeString(long timeMillis) {
         return ISO_8601.get().format(new Date(timeMillis));
diff --git a/common/src/com/android/tv/common/util/Debug.java b/common/src/com/android/tv/common/util/Debug.java
index 8e826ae..ab90874 100644
--- a/common/src/com/android/tv/common/util/Debug.java
+++ b/common/src/com/android/tv/common/util/Debug.java
@@ -23,11 +23,11 @@
 /** A class only for help developers. */
 public class Debug {
     /**
-     * A threshold of start up time, when the start up time of TV app is more than it, a warning
-     * will show to the developer.
+     * 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 TV app. */
+    /** 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. */
diff --git a/common/src/com/android/tv/common/util/LocationUtils.java b/common/src/com/android/tv/common/util/LocationUtils.java
index 9d44cf2..ee5119e 100644
--- a/common/src/com/android/tv/common/util/LocationUtils.java
+++ b/common/src/com/android/tv/common/util/LocationUtils.java
@@ -16,7 +16,9 @@
 
 package com.android.tv.common.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;
@@ -24,12 +26,13 @@
 import android.location.LocationManager;
 import android.os.Bundle;
 import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
 import android.text.TextUtils;
 import android.util.Log;
-
 import com.android.tv.common.BuildConfig;
 
+
+
+
 import java.io.IOException;
 import java.util.Collections;
 import java.util.HashSet;
@@ -62,41 +65,19 @@
         if (sApplicationContext == null) {
             sApplicationContext = context.getApplicationContext();
         }
-        /* Begin_AOSP_Comment_Out
-        if (!BuildConfig.AOSP) {
-            com.google.android.tv.livechannels.util.GoogleLocationUtilsHelper.startLocationUpdates(
-                    context, LocationUtils::updateAddress);
-            return null;
-        }
-        End_AOSP_Comment_Out */
         LocationUtilsHelper.startLocationUpdates();
         return null;
     }
 
-    @Nullable
-    static String getCurrentPostalCode(Context context) throws IOException {
-        Address address = getCurrentAddress(context);
-        if (address != null) {
-            Log.i(
-                    TAG,
-                    "Current country and postal code is "
-                            + address.getCountryName()
-                            + ", "
-                            + address.getPostalCode());
-            return address.getPostalCode();
-        }
-        return null;
-    }
-
     /** The listener used when address is updated. */
     public interface OnUpdateAddressListener {
         /**
          * Called when address is updated.
          *
-         * <p>This listener is removed when this method returns true.
+         * This listener is removed when this method returns true.
          *
          * @return {@code true} if the job has been finished and the listener needs to be removed;
-         *     {@code false} otherwise.
+         *         {@code false} otherwise.
          */
         boolean onUpdateAddress(Address address);
     }
@@ -104,8 +85,8 @@
     /**
      * Add an {@link OnUpdateAddressListener} instance.
      *
-     * <p>Note that the listener is removed automatically when {@link
-     * OnUpdateAddressListener#onUpdateAddress(Address)} is called and returns {@code true}.
+     * Note that the listener is removed automatically when
+     * {@link OnUpdateAddressListener#onUpdateAddress(Address)} is called and returns {@code true}.
      */
     public static void addOnUpdateAddressListener(OnUpdateAddressListener listener) {
         sOnUpdateAddressListeners.add(listener);
@@ -114,8 +95,8 @@
     /**
      * Remove an {@link OnUpdateAddressListener} instance if it exists.
      *
-     * <p>Note that the listener will be removed automatically when {@link
-     * OnUpdateAddressListener#onUpdateAddress(Address)} is called and returns {@code true}.
+     * Note that the listener will be removed automatically when
+     * {@link OnUpdateAddressListener#onUpdateAddress(Address)} is called and returns {@code true}.
      */
     public static void removeOnUpdateAddressListener(OnUpdateAddressListener listener) {
         sOnUpdateAddressListeners.remove(listener);
@@ -127,13 +108,6 @@
         if (sCountry != null) {
             return sCountry;
         }
-        /* Begin_AOSP_Comment_Out
-        if (!BuildConfig.AOSP) {
-            sCountry =
-                    com.google.android.tv.livechannels.util.GoogleLocationUtilsHelper
-                            .getDeviceCountry(context);
-        }
-        End_AOSP_Comment_Out */
         if (TextUtils.isEmpty(sCountry)) {
             sCountry = context.getResources().getConfiguration().locale.getCountry();
         }
diff --git a/common/src/com/android/tv/common/util/NetworkTrafficTags.java b/common/src/com/android/tv/common/util/NetworkTrafficTags.java
index 51b6c4d..3c94aed 100644
--- a/common/src/com/android/tv/common/util/NetworkTrafficTags.java
+++ b/common/src/com/android/tv/common/util/NetworkTrafficTags.java
@@ -20,7 +20,7 @@
 import android.support.annotation.NonNull;
 import java.util.concurrent.Executor;
 
-/** Constants for tagging network traffic in the TV app. */
+/** Constants for tagging network traffic in the Live channels app. */
 public final class NetworkTrafficTags {
 
     public static final int DEFAULT_LIVE_CHANNELS = 1;
@@ -43,16 +43,16 @@
 
         @Override
         public void execute(final @NonNull Runnable command) {
-            // TODO(b/62038127): robolectric does not support lamdas in unbundled apps
-            delegateExecutor.execute(
-                    () -> {
-                        TrafficStats.setThreadStatsTag(tag);
-                        try {
-                            command.run();
-                        } finally {
-                            TrafficStats.clearThreadStatsTag();
-                        }
-                    });
+      // TODO(b/62038127): robolectric does not support lamdas in unbundled apps
+      delegateExecutor.execute(
+          () -> {
+            TrafficStats.setThreadStatsTag(tag);
+            try {
+              command.run();
+            } finally {
+              TrafficStats.clearThreadStatsTag();
+            }
+          });
         }
     }
 
diff --git a/common/src/com/android/tv/common/util/PermissionUtils.java b/common/src/com/android/tv/common/util/PermissionUtils.java
index e241b91..ca1abdc 100644
--- a/common/src/com/android/tv/common/util/PermissionUtils.java
+++ b/common/src/com/android/tv/common/util/PermissionUtils.java
@@ -26,9 +26,6 @@
     private static Boolean sHasAccessAllEpgPermission;
     private static Boolean sHasAccessWatchedHistoryPermission;
     private static Boolean sHasModifyParentalControlsPermission;
-    private static Boolean sHasChangeHdmiCecActiveSource;
-    private static Boolean sHasReadContentRatingSystem;
-
 
     public static boolean hasAccessAllEpg(Context context) {
         if (sHasAccessAllEpgPermission == null) {
@@ -73,24 +70,4 @@
         return context.checkSelfPermission("android.permission.WRITE_EXTERNAL_STORAGE")
                 == PackageManager.PERMISSION_GRANTED;
     }
-
-    public static boolean hasChangeHdmiCecActiveSource(Context context) {
-        if (sHasChangeHdmiCecActiveSource == null) {
-            sHasChangeHdmiCecActiveSource =
-                    context.checkSelfPermission(
-                            "android.permission.CHANGE_HDMI_CEC_ACTIVE_SOURCE")
-                            == PackageManager.PERMISSION_GRANTED;
-        }
-        return sHasChangeHdmiCecActiveSource;
-    }
-
-    public static boolean hasReadContetnRatingSystem(Context context) {
-        if (sHasReadContentRatingSystem == null) {
-            sHasReadContentRatingSystem =
-                    context.checkSelfPermission(
-                            "android.permission.READ_CONTENT_RATING_SYSTEMS")
-                            == PackageManager.PERMISSION_GRANTED;
-        }
-        return sHasReadContentRatingSystem;
-    }
 }
diff --git a/common/src/com/android/tv/common/util/PostalCodeUtils.java b/common/src/com/android/tv/common/util/PostalCodeUtils.java
index 6ca3d48..c0917af 100644
--- a/common/src/com/android/tv/common/util/PostalCodeUtils.java
+++ b/common/src/com/android/tv/common/util/PostalCodeUtils.java
@@ -17,12 +17,12 @@
 package com.android.tv.common.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.common.CommonPreferences;
-
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.Locale;
@@ -62,7 +62,7 @@
     /** Returns {@code true} if postal code has been changed */
     public static boolean updatePostalCode(Context context)
             throws IOException, SecurityException, NoPostalCodeException {
-        String postalCode = LocationUtils.getCurrentPostalCode(context);
+        String postalCode = getPostalCode(context);
         String lastPostalCode = getLastPostalCode(context);
         if (TextUtils.isEmpty(postalCode)) {
             if (TextUtils.isEmpty(lastPostalCode)) {
@@ -92,6 +92,21 @@
         CommonPreferences.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() {}
diff --git a/common/src/com/android/tv/common/util/SystemProperties.java b/common/src/com/android/tv/common/util/SystemProperties.java
index 72920b6..6ac2907 100644
--- a/common/src/com/android/tv/common/util/SystemProperties.java
+++ b/common/src/com/android/tv/common/util/SystemProperties.java
@@ -21,6 +21,25 @@
 /** A convenience class for getting TV related system properties. */
 public final class SystemProperties {
 
+    /** Allow Google Analytics for eng builds. */
+    public static final BooleanSystemProperty ALLOW_ANALYTICS_IN_ENG =
+            new BooleanSystemProperty("tv_allow_analytics_in_eng", false);
+
+    /** Allow Strict mode for debug builds. */
+    public static final BooleanSystemProperty ALLOW_STRICT_MODE =
+            new BooleanSystemProperty("tv_allow_strict_mode", true);
+
+    /** When true {@link android.view.KeyEvent}s are logged. Defaults to false. */
+    public static final BooleanSystemProperty LOG_KEYEVENT =
+            new BooleanSystemProperty("tv_log_keyevent", false);
+    /** When true debug keys are used. Defaults to false. */
+    public static final BooleanSystemProperty USE_DEBUG_KEYS =
+            new BooleanSystemProperty("tv_use_debug_keys", false);
+
+    /** Send {@link com.android.tv.analytics.Tracker} information. Defaults to {@code true}. */
+    public static final BooleanSystemProperty USE_TRACKER =
+            new BooleanSystemProperty("tv_use_tracker", true);
+
     /** Allow third party inputs. */
     public static final BooleanSystemProperty ALLOW_THIRD_PARTY_INPUTS =
             new BooleanSystemProperty("ro.tv_allow_third_party_inputs", true);
diff --git a/common/tests/robotests/src/com/android/tv/common/TvContentRatingCacheTest.java b/common/tests/robotests/src/com/android/tv/common/TvContentRatingCacheTest.java
deleted file mode 100644
index 521b220..0000000
--- a/common/tests/robotests/src/com/android/tv/common/TvContentRatingCacheTest.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * 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.common;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
-
-import android.content.ComponentCallbacks2;
-import android.media.tv.TvContentRating;
-
-import com.android.tv.testing.constants.ConfigConstants;
-import com.android.tv.testing.constants.TvContentRatingConstants;
-
-import com.google.common.collect.ImmutableList;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-/** Test for {@link TvContentRatingCache}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-public class TvContentRatingCacheTest {
-    /** 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();
-
-    @Before
-    public void setUp() {
-        mCache.performTrimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE);
-    }
-
-    @After
-    public void tearDown() {
-        mCache.performTrimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE);
-    }
-
-    @Test
-    public void testGetRatings_US_TV_MA() {
-        ImmutableList<TvContentRating> result =
-                mCache.getRatings(TvContentRatingConstants.STRING_US_TV_MA);
-        assertThat(result).contains(TvContentRatingConstants.CONTENT_RATING_US_TV_MA);
-    }
-
-    @Test
-    public void testGetRatings_US_TV_MA_same() {
-        ImmutableList<TvContentRating> first =
-                mCache.getRatings(TvContentRatingConstants.STRING_US_TV_MA);
-        ImmutableList<TvContentRating> second =
-                mCache.getRatings(TvContentRatingConstants.STRING_US_TV_MA);
-        assertThat(first).isSameInstanceAs(second);
-    }
-
-    @Test
-    public void testGetRatings_US_TV_MA_diffAfterClear() {
-        ImmutableList<TvContentRating> first =
-                mCache.getRatings(TvContentRatingConstants.STRING_US_TV_MA);
-        mCache.performTrimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE);
-        ImmutableList<TvContentRating> second =
-                mCache.getRatings(TvContentRatingConstants.STRING_US_TV_MA);
-        assertThat(first).isNotSameInstanceAs(second);
-    }
-
-    @Test
-    public void testGetRatings_TWO_orderDoesNotMatter() {
-        ImmutableList<TvContentRating> first = mCache.getRatings(MA_AND_Y7);
-        ImmutableList<TvContentRating> second = mCache.getRatings(Y7_AND_MA);
-        assertThat(first).isSameInstanceAs(second);
-    }
-
-    @Test
-    public void testContentRatingsToString_null() {
-        String result = TvContentRatingCache.contentRatingsToString(null);
-        assertWithMessage("ratings string").that(result).isNull();
-    }
-
-    @Test
-    public void testContentRatingsToString_none() {
-        String result = TvContentRatingCache.contentRatingsToString(ImmutableList.of());
-        assertWithMessage("ratings string").that(result).isEmpty();
-    }
-
-    @Test
-    public void testContentRatingsToString_one() {
-        String result =
-                TvContentRatingCache.contentRatingsToString(
-                        ImmutableList.of(TvContentRatingConstants.CONTENT_RATING_US_TV_MA));
-        assertWithMessage("ratings string")
-                .that(result)
-                .isEqualTo(TvContentRatingConstants.STRING_US_TV_MA);
-    }
-
-    @Test
-    public void testContentRatingsToString_twoInOrder() {
-        String result =
-                TvContentRatingCache.contentRatingsToString(
-                        ImmutableList.of(
-                                TvContentRatingConstants.CONTENT_RATING_US_TV_MA,
-                                TvContentRatingConstants.CONTENT_RATING_US_TV_Y7_US_TV_FV));
-        assertWithMessage("ratings string").that(result).isEqualTo(MA_AND_Y7);
-    }
-
-    @Test
-    public void testContentRatingsToString_twoNotInOrder() {
-        String result =
-                TvContentRatingCache.contentRatingsToString(
-                        ImmutableList.of(
-                                TvContentRatingConstants.CONTENT_RATING_US_TV_Y7_US_TV_FV,
-                                TvContentRatingConstants.CONTENT_RATING_US_TV_MA));
-        assertWithMessage("ratings string").that(result).isEqualTo(MA_AND_Y7);
-    }
-
-    @Test
-    public void testContentRatingsToString_double() {
-        String result =
-                TvContentRatingCache.contentRatingsToString(
-                        ImmutableList.of(
-                                TvContentRatingConstants.CONTENT_RATING_US_TV_MA,
-                                TvContentRatingConstants.CONTENT_RATING_US_TV_MA));
-        assertWithMessage("ratings string")
-                .that(result)
-                .isEqualTo(TvContentRatingConstants.STRING_US_TV_MA);
-    }
-
-    @Test
-    public void testStringToContentRatings_null() {
-        assertThat(TvContentRatingCache.stringToContentRatings(null)).isEmpty();
-    }
-
-    @Test
-    public void testStringToContentRatings_none() {
-        assertThat(TvContentRatingCache.stringToContentRatings("")).isEmpty();
-    }
-
-    @Test
-    public void testStringToContentRatings_bad() {
-        assertThat(TvContentRatingCache.stringToContentRatings("bad")).isEmpty();
-    }
-
-    @Test
-    public void testStringToContentRatings_oneGoodOneBad() {
-        ImmutableList<TvContentRating> results =
-                TvContentRatingCache.stringToContentRatings(
-                        TvContentRatingConstants.STRING_US_TV_Y7_US_TV_FV + ",bad");
-        assertWithMessage("ratings")
-                .that(results)
-                .containsExactly(TvContentRatingConstants.CONTENT_RATING_US_TV_Y7_US_TV_FV);
-    }
-
-    @Test
-    public void testStringToContentRatings_one() {
-        ImmutableList<TvContentRating> results =
-                TvContentRatingCache.stringToContentRatings(
-                        TvContentRatingConstants.STRING_US_TV_Y7_US_TV_FV);
-        assertWithMessage("ratings")
-                .that(results)
-                .containsExactly(TvContentRatingConstants.CONTENT_RATING_US_TV_Y7_US_TV_FV);
-    }
-
-    @Test
-    public void testStringToContentRatings_twoNotInOrder() {
-        ImmutableList<TvContentRating> results =
-                TvContentRatingCache.stringToContentRatings(Y7_AND_MA);
-        assertWithMessage("ratings")
-                .that(results)
-                .containsExactly(
-                        TvContentRatingConstants.CONTENT_RATING_US_TV_MA,
-                        TvContentRatingConstants.CONTENT_RATING_US_TV_Y7_US_TV_FV);
-    }
-
-    @Test
-    public void testStringToContentRatings_twoInOrder() {
-        ImmutableList<TvContentRating> results =
-                TvContentRatingCache.stringToContentRatings(MA_AND_Y7);
-        assertWithMessage("ratings")
-                .that(results)
-                .containsExactly(
-                        TvContentRatingConstants.CONTENT_RATING_US_TV_MA,
-                        TvContentRatingConstants.CONTENT_RATING_US_TV_Y7_US_TV_FV);
-    }
-
-    @Test
-    public void testStringToContentRatings_double() {
-        ImmutableList<TvContentRating> results =
-                TvContentRatingCache.stringToContentRatings(
-                        TvContentRatingConstants.STRING_US_TV_MA
-                                + ","
-                                + TvContentRatingConstants.STRING_US_TV_MA);
-        assertWithMessage("ratings")
-                .that(results)
-                .containsExactly((TvContentRatingConstants.CONTENT_RATING_US_TV_MA));
-
-        assertThat(results).containsExactly(TvContentRatingConstants.CONTENT_RATING_US_TV_MA);
-    }
-}
diff --git a/common/tests/robotests/src/com/android/tv/common/actions/InputSetupActionUtilsTest.java b/common/tests/robotests/src/com/android/tv/common/actions/InputSetupActionUtilsTest.java
deleted file mode 100644
index be586be..0000000
--- a/common/tests/robotests/src/com/android/tv/common/actions/InputSetupActionUtilsTest.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (C) 2018 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.actions;
-
-import static com.google.android.libraries.testing.truth.BundleSubject.assertThat;
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Intent;
-import android.os.Bundle;
-
-import com.android.tv.testing.constants.ConfigConstants;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-/** Tests for {@link InputSetupActionUtils} */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-public class InputSetupActionUtilsTest {
-
-    @Test
-    public void hasInputSetupAction_launchInputSetup() {
-        Intent intent = new Intent("com.android.tv.action.LAUNCH_INPUT_SETUP");
-        assertThat(InputSetupActionUtils.hasInputSetupAction(intent)).isTrue();
-    }
-
-    @Test
-    public void hasInputSetupAction_googleLaunchInputSetup() {
-        Intent intent = new Intent("com.google.android.tv.action.LAUNCH_INPUT_SETUP");
-        assertThat(InputSetupActionUtils.hasInputSetupAction(intent)).isTrue();
-    }
-
-    @Test
-    public void hasInputSetupAction_bad() {
-        Intent intent = new Intent("com.example.action.LAUNCH_INPUT_SETUP");
-        assertThat(InputSetupActionUtils.hasInputSetupAction(intent)).isFalse();
-    }
-
-    @Test
-    public void getExtraActivityAfter_null() {
-        Intent intent = new Intent();
-        assertThat(InputSetupActionUtils.getExtraActivityAfter(intent)).isNull();
-    }
-
-    @Test
-    public void getExtraActivityAfter_activityAfter() {
-        Intent intent = new Intent();
-        Intent after = new Intent("after");
-        intent.putExtra("com.android.tv.intent.extra.ACTIVITY_AFTER_COMPLETION", after);
-        assertThat(InputSetupActionUtils.getExtraActivityAfter(intent)).isEqualTo(after);
-    }
-
-    @Test
-    public void getExtraActivityAfter_googleActivityAfter() {
-        Intent intent = new Intent();
-        Intent after = new Intent("google_setup");
-        intent.putExtra("com.google.android.tv.intent.extra.ACTIVITY_AFTER_COMPLETION", after);
-        assertThat(InputSetupActionUtils.getExtraActivityAfter(intent)).isEqualTo(after);
-    }
-
-    @Test
-    public void getExtraSetupIntent_null() {
-        Intent intent = new Intent();
-        assertThat(InputSetupActionUtils.getExtraSetupIntent(intent)).isNull();
-    }
-
-    @Test
-    public void getExtraSetupIntent_setupIntent() {
-        Intent intent = new Intent();
-        Intent setup = new Intent("setup");
-        intent.putExtra("com.android.tv.extra.SETUP_INTENT", setup);
-        assertThat(InputSetupActionUtils.getExtraSetupIntent(intent)).isEqualTo(setup);
-    }
-
-    @Test
-    public void getExtraSetupIntent_googleSetupIntent() {
-        Intent intent = new Intent();
-        Intent setup = new Intent("google_setup");
-        intent.putExtra("com.google.android.tv.extra.SETUP_INTENT", setup);
-        assertThat(InputSetupActionUtils.getExtraSetupIntent(intent)).isEqualTo(setup);
-    }
-
-    @Test
-    public void removeSetupIntent_empty() {
-        Bundle extras = new Bundle();
-        InputSetupActionUtils.removeSetupIntent(extras);
-        assertThat(extras).exactlyMatches(new Bundle());
-    }
-
-    @Test
-    public void removeSetupIntent_other() {
-        Bundle extras = createTestBundle();
-        Bundle expected = createTestBundle();
-        InputSetupActionUtils.removeSetupIntent(extras);
-        assertThat(extras).exactlyMatches(expected);
-    }
-
-    @Test
-    public void removeSetupIntent_setup() {
-        Bundle extras = createTestBundle();
-        Bundle expected = createTestBundle();
-        Intent setup = new Intent("setup");
-        extras.putParcelable("com.android.tv.extra.SETUP_INTENT", setup);
-        InputSetupActionUtils.removeSetupIntent(extras);
-        assertThat(extras).exactlyMatches(expected);
-    }
-
-    @Test
-    public void removeSetupIntent_googleSetup() {
-        Bundle extras = createTestBundle();
-        Bundle expected = createTestBundle();
-        Intent googleSetup = new Intent("googleSetup");
-        extras.putParcelable("com.google.android.tv.extra.SETUP_INTENT", googleSetup);
-        InputSetupActionUtils.removeSetupIntent(extras);
-        assertThat(extras).exactlyMatches(expected);
-    }
-
-    @Test
-    public void removeSetupIntent_bothSetups() {
-        Bundle extras = createTestBundle();
-        Bundle expected = createTestBundle();
-        Intent setup = new Intent("setup");
-        extras.putParcelable("com.android.tv.extra.SETUP_INTENT", setup);
-        Intent googleSetup = new Intent("googleSetup");
-        extras.putParcelable("com.google.android.tv.extra.SETUP_INTENT", googleSetup);
-        InputSetupActionUtils.removeSetupIntent(extras);
-        assertThat(extras).exactlyMatches(expected);
-    }
-
-    private static Bundle createTestBundle() {
-        Bundle extras = new Bundle();
-        extras.putInt("other", 1);
-        return extras;
-    }
-}
diff --git a/common/tests/robotests/src/com/android/tv/common/compat/TvInputInfoCompatTest.java b/common/tests/robotests/src/com/android/tv/common/compat/TvInputInfoCompatTest.java
deleted file mode 100644
index 5c10c00..0000000
--- a/common/tests/robotests/src/com/android/tv/common/compat/TvInputInfoCompatTest.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2018 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.compat;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static junit.framework.Assert.fail;
-
-import android.content.pm.ResolveInfo;
-import android.content.res.XmlResourceParser;
-import android.media.tv.TvInputInfo;
-
-import androidx.test.InstrumentationRegistry;
-
-import com.android.tv.testing.constants.ConfigConstants;
-import com.android.tv.testing.utils.TestUtils;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlPullParserFactory;
-
-import java.io.StringReader;
-
-/** Tests for {@link TvInputInfoCompat}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-public class TvInputInfoCompatTest {
-    private TvInputInfoCompat mTvInputInfoCompat;
-    private String mInputXml;
-
-    @Before
-    public void setUp() throws Exception {
-        ResolveInfo resolveInfo = TestUtils.createResolveInfo("test", "test");
-        TvInputInfo info =
-                TestUtils.createTvInputInfo(
-                        resolveInfo, "test_input", "test1", TvInputInfo.TYPE_OTHER, false);
-        mTvInputInfoCompat =
-                new TvInputInfoCompat(InstrumentationRegistry.getTargetContext(), info) {
-                    @Override
-                    XmlPullParser getXmlResourceParser() {
-                        XmlPullParser xpp = null;
-                        try {
-                            xpp = XmlPullParserFactory.newInstance().newPullParser();
-                            xpp.setInput(new StringReader(mInputXml));
-                            xpp.setFeature(XmlResourceParser.FEATURE_PROCESS_NAMESPACES, true);
-                        } catch (XmlPullParserException e) {
-                            fail("failed in setUp() " + e.getMessage());
-                        }
-                        return xpp;
-                    }
-                };
-    }
-
-    @Test
-    public void testGetAttributeValue_notTvInputTag() {
-        mInputXml =
-                "<not-tv-input xmlns:android=\"http://schemas.android.com/apk/res/android\"\n"
-                        + "    android:setupActivity=\"\"\n"
-                        + "    android:settingsActivity=\"\"/>\n";
-        assertThat(mTvInputInfoCompat.getExtras()).isEmpty();
-    }
-
-    @Test
-    public void testGetAttributeValue_noExtra() {
-        mInputXml =
-                "<not-tv-input xmlns:android=\"http://schemas.android.com/apk/res/android\"\n"
-                        + "    android:setupActivity=\"\"\n"
-                        + "    android:settingsActivity=\"\"/>\n";
-        assertThat(mTvInputInfoCompat.getExtras()).isEmpty();
-    }
-
-    @Test
-    public void testGetAttributeValue() {
-        mInputXml =
-                "<tv-input xmlns:android=\"http://schemas.android.com/apk/res/android\"\n"
-                        + "    android:setupActivity=\"\"\n"
-                        + "    android:settingsActivity=\"\">\n"
-                        + "      <extra android:name=\"otherAttr1\" android:value=\"false\" />\n"
-                        + "      <extra android:name=\"otherAttr2\" android:value=\"false\" />\n"
-                        + "      <extra android:name="
-                        + "          \"com.android.tv.common.compat.tvinputinfocompat.audioOnly\""
-                        + "          android:value=\"true\" />\n"
-                        + "</tv-input>";
-        assertThat(mTvInputInfoCompat.getExtras())
-                .containsExactly(
-                        "otherAttr1",
-                        "false",
-                        "otherAttr2",
-                        "false",
-                        "com.android.tv.common.compat.tvinputinfocompat.audioOnly",
-                        "true");
-    }
-}
diff --git a/common/tests/robotests/src/com/android/tv/common/compat/internal/PrivateCommandTest.java b/common/tests/robotests/src/com/android/tv/common/compat/internal/PrivateCommandTest.java
deleted file mode 100644
index aa9221f..0000000
--- a/common/tests/robotests/src/com/android/tv/common/compat/internal/PrivateCommandTest.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2018 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.compat.internal;
-
-import static org.mockito.Mockito.only;
-import static org.mockito.Mockito.verify;
-
-import com.android.tv.common.compat.api.SessionCompatCommands;
-import com.android.tv.testing.constants.ConfigConstants;
-
-import com.google.protobuf.InvalidProtocolBufferException;
-import com.google.testing.mockito.Mocks;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-/**
- * Tests sending {@link Commands.PrivateCommand}s to a {@link SessionCompatCommands} from {@link
- * TvViewCompatProcessor} via {@link TifSessionCompatProcessor}.
- */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-public class PrivateCommandTest {
-    @Rule public final Mocks mocks = new Mocks(this);
-
-    @Mock SessionCompatCommands mCallback;
-
-    private TvViewCompatProcessor mTvViewCompatProcessor;
-
-    @Before
-    public void setUp() {
-        TifSessionCompatProcessor sessionCompatProcessor =
-                new TifSessionCompatProcessor(null, mCallback);
-        mTvViewCompatProcessor =
-                new TvViewCompatProcessor(sessionCompatProcessor::handleAppPrivateCommand);
-    }
-
-    @Test
-    public void notifyDevToast() throws InvalidProtocolBufferException {
-        mTvViewCompatProcessor.devMessage("Hello Developers");
-        verify(mCallback, only()).onDevMessage("Hello Developers");
-    }
-}
diff --git a/common/tests/robotests/src/com/android/tv/common/compat/internal/PrivateRecordingCommandTest.java b/common/tests/robotests/src/com/android/tv/common/compat/internal/PrivateRecordingCommandTest.java
deleted file mode 100644
index 1a3c091..0000000
--- a/common/tests/robotests/src/com/android/tv/common/compat/internal/PrivateRecordingCommandTest.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2018 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.compat.internal;
-
-import static org.mockito.Mockito.only;
-import static org.mockito.Mockito.verify;
-
-import com.android.tv.common.compat.api.RecordingSessionCompatCommands;
-import com.android.tv.testing.constants.ConfigConstants;
-
-import com.google.protobuf.InvalidProtocolBufferException;
-import com.google.testing.mockito.Mocks;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-/**
- * Tests sending {@link RecordingCommands.PrivateRecordingCommand}s to a {@link
- * RecordingSessionCompatCommands} from {@link RecordingClientCompatProcessor} via {@link
- * RecordingSessionCompatProcessor}.
- */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-public class PrivateRecordingCommandTest {
-    @Rule public final Mocks mocks = new Mocks(this);
-
-    @Mock private RecordingSessionCompatCommands mCallback;
-
-    private RecordingClientCompatProcessor mCompatProcessor;
-
-    @Before
-    public void setUp() {
-        RecordingSessionCompatProcessor sessionCompatProcessor =
-                new RecordingSessionCompatProcessor(null, mCallback);
-        mCompatProcessor =
-                new RecordingClientCompatProcessor(
-                        sessionCompatProcessor::handleAppPrivateCommand, null);
-    }
-
-    @Test
-    public void notifyDevToast() throws InvalidProtocolBufferException {
-        mCompatProcessor.devMessage("Hello Recorders");
-        verify(mCallback, only()).onDevMessage("Hello Recorders");
-    }
-}
diff --git a/common/tests/robotests/src/com/android/tv/common/compat/internal/RecordingSessionEventTest.java b/common/tests/robotests/src/com/android/tv/common/compat/internal/RecordingSessionEventTest.java
deleted file mode 100644
index 3de3a6d..0000000
--- a/common/tests/robotests/src/com/android/tv/common/compat/internal/RecordingSessionEventTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2018 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.compat.internal;
-
-import static org.mockito.Mockito.only;
-import static org.mockito.Mockito.verify;
-
-import com.android.tv.common.compat.api.RecordingClientCallbackCompatEvents;
-import com.android.tv.testing.constants.ConfigConstants;
-
-import com.google.protobuf.InvalidProtocolBufferException;
-import com.google.testing.mockito.Mocks;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-/**
- * Tests sending {@link RecordingEvents.RecordingSessionEvent}s to a {@link
- * RecordingClientCallbackCompatEvents} from {@link RecordingSessionCompatProcessor} via {@link
- * RecordingClientCompatProcessor}.
- */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-public class RecordingSessionEventTest {
-    @Rule public final Mocks mocks = new Mocks(this);
-
-    @Mock RecordingClientCallbackCompatEvents mCallback;
-
-    private RecordingSessionCompatProcessor mCompatProcess;
-
-    @Before
-    public void setUp() {
-        RecordingClientCompatProcessor compatProcessor =
-                new RecordingClientCompatProcessor(null, mCallback);
-        mCompatProcess =
-                new RecordingSessionCompatProcessor(
-                        (event, data) -> compatProcessor.handleEvent("testinput", event, data),
-                        null);
-    }
-
-    @Test
-    public void notifyDevToast() throws InvalidProtocolBufferException {
-        mCompatProcess.notifyDevToast("Recording");
-        verify(mCallback, only()).onDevToast("testinput", "Recording");
-    }
-
-    @Test
-    public void notifyRecordingStarted() throws InvalidProtocolBufferException {
-        mCompatProcess.notifyRecordingStarted("file:example");
-        verify(mCallback, only()).onRecordingStarted("testinput", "file:example");
-    }
-}
diff --git a/common/tests/robotests/src/com/android/tv/common/compat/internal/SessionEventTest.java b/common/tests/robotests/src/com/android/tv/common/compat/internal/SessionEventTest.java
deleted file mode 100644
index e65297c..0000000
--- a/common/tests/robotests/src/com/android/tv/common/compat/internal/SessionEventTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2018 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.compat.internal;
-
-import static org.mockito.Mockito.only;
-import static org.mockito.Mockito.verify;
-
-import com.android.tv.common.compat.api.TvInputCallbackCompatEvents;
-import com.android.tv.testing.constants.ConfigConstants;
-
-import com.google.protobuf.InvalidProtocolBufferException;
-import com.google.testing.mockito.Mocks;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-/**
- * Tests sending {@link Events.SessionEvent}s to a {@link TvInputCallbackCompatEvents} from {@link
- * TifSessionCompatProcessor} via {@link TvViewCompatProcessor}.
- */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-public class SessionEventTest {
-    @Rule public final Mocks mocks = new Mocks(this);
-
-    @Mock TvInputCallbackCompatEvents mCallback;
-
-    private TifSessionCompatProcessor mCompatProcess;
-
-    @Before
-    public void setUp() {
-        TvViewCompatProcessor tvViewCompatProcessor = new TvViewCompatProcessor(null);
-        tvViewCompatProcessor.setCallback(mCallback);
-        mCompatProcess =
-                new TifSessionCompatProcessor(
-                        (event, data) ->
-                                tvViewCompatProcessor.handleEvent("testinput", event, data),
-                        null);
-    }
-
-    @Test
-    public void notifyDevToast() throws InvalidProtocolBufferException {
-        mCompatProcess.notifyDevToast("testing");
-        verify(mCallback, only()).onDevToast("testinput", "testing");
-    }
-
-    @Test
-    public void notifySignalStrength() throws InvalidProtocolBufferException {
-        mCompatProcess.notifySignalStrength(3);
-        verify(mCallback, only()).onSignalStrength("testinput", 3);
-    }
-}
diff --git a/common/tests/robotests/src/com/android/tv/common/dev/DeveloperPreferenceTest.java b/common/tests/robotests/src/com/android/tv/common/dev/DeveloperPreferenceTest.java
deleted file mode 100644
index a9c15ad..0000000
--- a/common/tests/robotests/src/com/android/tv/common/dev/DeveloperPreferenceTest.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2019 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.dev;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import com.android.tv.testing.constants.ConfigConstants;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-/** Test for {@link DeveloperPreference}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-public class DeveloperPreferenceTest {
-
-    @Test
-    public void createBoolean_default_true() {
-        DeveloperPreference<Boolean> devPref = DeveloperPreference.create("test", true);
-        assertThat(devPref.get(RuntimeEnvironment.systemContext)).isTrue();
-        DeveloperPreference.getPreferences(RuntimeEnvironment.systemContext)
-                .edit()
-                .putBoolean("test", false)
-                .apply();
-        assertThat(devPref.get(RuntimeEnvironment.systemContext)).isFalse();
-    }
-
-    @Test
-    public void create_integer_default_one() {
-        DeveloperPreference<Integer> devPref = DeveloperPreference.create("test", 1);
-        assertThat(devPref.get(RuntimeEnvironment.systemContext)).isEqualTo(1);
-        DeveloperPreference.getPreferences(RuntimeEnvironment.systemContext)
-                .edit()
-                .putInt("test", 2)
-                .apply();
-        assertThat(devPref.get(RuntimeEnvironment.systemContext)).isEqualTo(2);
-    }
-}
diff --git a/common/tests/robotests/src/com/android/tv/common/support/tis/BaseTvInputServiceTest.java b/common/tests/robotests/src/com/android/tv/common/support/tis/BaseTvInputServiceTest.java
deleted file mode 100644
index 88b0215..0000000
--- a/common/tests/robotests/src/com/android/tv/common/support/tis/BaseTvInputServiceTest.java
+++ /dev/null
@@ -1,147 +0,0 @@
-package com.android.tv.common.support.tis;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Intent;
-import android.media.tv.TvContentRating;
-import android.media.tv.TvInputManager;
-import android.net.Uri;
-import android.os.Build;
-import android.support.annotation.Nullable;
-import android.view.Surface;
-
-import com.android.tv.common.support.tis.TifSession.TifSessionCallbacks;
-import com.android.tv.common.support.tis.TifSession.TifSessionFactory;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.Robolectric;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.android.controller.ServiceController;
-import org.robolectric.annotation.Config;
-
-/** Tests for {@link BaseTvInputService}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(minSdk = Build.VERSION_CODES.LOLLIPOP, maxSdk = Build.VERSION_CODES.P)
-public class BaseTvInputServiceTest {
-
-    private static class TestTvInputService extends BaseTvInputService {
-
-        private final SessionManager sessionManager = new SimpleSessionManager(1);
-
-        private int parentalControlsChangedCount = 0;
-        private final TifSessionFactory sessionFactory;
-
-        private TestTvInputService() {
-            super();
-            this.sessionFactory =
-                    new TifSessionFactory() {
-                        @Override
-                        public TifSession create(TifSessionCallbacks callbacks, String inputId) {
-                            return new TifSession(callbacks) {
-                                @Override
-                                public boolean onSetSurface(@Nullable Surface surface) {
-                                    return false;
-                                }
-
-                                @Override
-                                public void onSurfaceChanged(int format, int width, int height) {}
-
-                                @Override
-                                public void onSetStreamVolume(float volume) {}
-
-                                @Override
-                                public boolean onTune(Uri channelUri) {
-                                    return false;
-                                }
-
-                                @Override
-                                public void onSetCaptionEnabled(boolean enabled) {}
-
-                                @Override
-                                public void onUnblockContent(TvContentRating unblockedRating) {}
-
-                                @Override
-                                public void onParentalControlsChanged() {
-                                    parentalControlsChangedCount++;
-                                }
-                            };
-                        }
-                    };
-        }
-
-        @Override
-        protected TifSessionFactory getTifSessionFactory() {
-            return sessionFactory;
-        }
-
-        @Override
-        protected SessionManager getSessionManager() {
-            return sessionManager;
-        }
-
-        private int getParentalControlsChangedCount() {
-            return parentalControlsChangedCount;
-        }
-    }
-
-    TestTvInputService tvInputService;
-    ServiceController<TestTvInputService> controller;
-
-    @Before
-    public void setUp() {
-        controller = Robolectric.buildService(TestTvInputService.class);
-        tvInputService = controller.create().get();
-    }
-
-    @Test
-    public void createSession_once() {
-        assertThat(tvInputService.onCreateSession("test")).isNotNull();
-    }
-
-    @Test
-    public void createSession_twice() {
-        WrappedSession first = tvInputService.onCreateSession("test");
-        assertThat(first).isNotNull();
-        WrappedSession second = tvInputService.onCreateSession("test");
-        assertThat(second).isNull();
-    }
-
-    @Test
-    public void createSession_release() {
-        WrappedSession first = tvInputService.onCreateSession("test");
-        assertThat(first).isNotNull();
-        first.onRelease();
-        WrappedSession second = tvInputService.onCreateSession("test");
-        assertThat(second).isNotNull();
-        assertThat(second).isNotSameInstanceAs(first);
-    }
-
-    @Test
-    public void testReceiver_actionEnabledChanged() {
-        tvInputService.getSessionManager().addSession(tvInputService.onCreateSession("test"));
-        tvInputService.broadcastReceiver.onReceive(
-                RuntimeEnvironment.application,
-                new Intent(TvInputManager.ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED));
-        assertThat(tvInputService.getParentalControlsChangedCount()).isEqualTo(1);
-    }
-
-    @Test
-    public void testReceiver_actionBlockedChanged() {
-        tvInputService.getSessionManager().addSession(tvInputService.onCreateSession("test"));
-        tvInputService.broadcastReceiver.onReceive(
-                RuntimeEnvironment.application,
-                new Intent(TvInputManager.ACTION_BLOCKED_RATINGS_CHANGED));
-        assertThat(tvInputService.getParentalControlsChangedCount()).isEqualTo(1);
-    }
-
-    @Test
-    public void testReceiver_invalidAction() {
-        tvInputService.getSessionManager().addSession(tvInputService.onCreateSession("test"));
-        tvInputService.broadcastReceiver.onReceive(
-                RuntimeEnvironment.application, new Intent("test"));
-        assertThat(tvInputService.getParentalControlsChangedCount()).isEqualTo(0);
-    }
-}
diff --git a/common/tests/robotests/src/com/android/tv/common/support/tis/SimpleSessionManagerTest.java b/common/tests/robotests/src/com/android/tv/common/support/tis/SimpleSessionManagerTest.java
deleted file mode 100644
index 3972559..0000000
--- a/common/tests/robotests/src/com/android/tv/common/support/tis/SimpleSessionManagerTest.java
+++ /dev/null
@@ -1,124 +0,0 @@
-package com.android.tv.common.support.tis;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.media.tv.TvContentRating;
-import android.net.Uri;
-import android.os.Build;
-import android.support.annotation.FloatRange;
-import android.support.annotation.Nullable;
-import android.view.Surface;
-
-import com.android.tv.common.support.tis.TifSession.TifSessionCallbacks;
-import com.android.tv.common.support.tis.TifSession.TifSessionFactory;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-/** Tests for {@link SimpleSessionManager}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(minSdk = Build.VERSION_CODES.LOLLIPOP, maxSdk = Build.VERSION_CODES.P)
-public class SimpleSessionManagerTest {
-
-    private SimpleSessionManager sessionManager;
-
-    @Before
-    public void setup() {
-        sessionManager = new SimpleSessionManager(1);
-    }
-
-    @Test
-    public void canCreateSession_none() {
-        assertThat(sessionManager.canCreateNewSession()).isTrue();
-    }
-
-    @Test
-    public void canCreateSession_one() {
-        sessionManager.addSession(createTestSession());
-        assertThat(sessionManager.canCreateNewSession()).isFalse();
-    }
-
-    @Test
-    public void addSession() {
-        assertThat(sessionManager.getSessionCount()).isEqualTo(0);
-        sessionManager.addSession(createTestSession());
-        assertThat(sessionManager.getSessionCount()).isEqualTo(1);
-    }
-
-    @Test
-    public void onRelease() {
-        WrappedSession testSession = createTestSession();
-        sessionManager.addSession(testSession);
-        assertThat(sessionManager.getSessionCount()).isEqualTo(1);
-        testSession.onRelease();
-        assertThat(sessionManager.getSessionCount()).isEqualTo(0);
-    }
-
-    @Test
-    public void onRelease_withUnRegisteredSession() {
-        WrappedSession testSession = createTestSession();
-        sessionManager.addSession(createTestSession());
-        assertThat(sessionManager.getSessionCount()).isEqualTo(1);
-        testSession.onRelease();
-        assertThat(sessionManager.getSessionCount()).isEqualTo(1);
-    }
-
-    @Test
-    public void getSessions() {
-        WrappedSession testSession = createTestSession();
-        sessionManager.addSession(testSession);
-        assertThat(sessionManager.getSessions()).containsExactly(testSession);
-    }
-
-    private WrappedSession createTestSession() {
-        return new WrappedSession(
-                RuntimeEnvironment.application,
-                sessionManager,
-                new TestTifSessionFactory(),
-                "testInputId");
-    }
-
-    private static final class TestTifSessionFactory implements TifSessionFactory {
-
-        @Override
-        public TifSession create(TifSessionCallbacks callbacks, String inputId) {
-            return new TestTifSession(callbacks);
-        }
-    }
-
-    private static final class TestTifSession extends TifSession {
-
-        private TestTifSession(TifSessionCallbacks callbacks) {
-            super(callbacks);
-        }
-
-        @Override
-        public void onRelease() {}
-
-        @Override
-        public boolean onSetSurface(@Nullable Surface surface) {
-            return false;
-        }
-
-        @Override
-        public void onSurfaceChanged(int format, int width, int height) {}
-
-        @Override
-        public void onSetStreamVolume(@FloatRange(from = 0.0, to = 1.0) float volume) {}
-
-        @Override
-        public boolean onTune(Uri channelUri) {
-            return false;
-        }
-
-        @Override
-        public void onSetCaptionEnabled(boolean enabled) {}
-
-        @Override
-        public void onUnblockContent(TvContentRating unblockedRating) {}
-    }
-}
diff --git a/common/tests/robotests/src/com/android/tv/common/support/tis/TisSessionTest.java b/common/tests/robotests/src/com/android/tv/common/support/tis/TisSessionTest.java
deleted file mode 100644
index e2f849e..0000000
--- a/common/tests/robotests/src/com/android/tv/common/support/tis/TisSessionTest.java
+++ /dev/null
@@ -1,209 +0,0 @@
-package com.android.tv.common.support.tis;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.media.tv.TvContentRating;
-import android.media.tv.TvInputManager;
-import android.media.tv.TvTrackInfo;
-import android.net.Uri;
-import android.os.Build;
-import android.support.annotation.FloatRange;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.util.Pair;
-import android.view.Surface;
-import android.view.View;
-
-import com.android.tv.common.support.tis.TifSession.TifSessionCallbacks;
-
-import com.google.common.collect.ImmutableList;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-import java.util.List;
-
-/** Tests for {@link TifSession}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(minSdk = Build.VERSION_CODES.LOLLIPOP, maxSdk = Build.VERSION_CODES.P)
-public class TisSessionTest {
-
-    private TestSession testSession;
-    private TestCallback testCallback;
-
-    @Before
-    public void setup() {
-        testCallback = new TestCallback();
-        testSession = new TestSession(testCallback);
-    }
-
-    @Test
-    public void notifyChannelReturned() {
-        Uri uri = Uri.parse("http://example.com");
-        testSession.notifyChannelRetuned(uri);
-        assertThat(testCallback.channelUri).isEqualTo(uri);
-    }
-
-    @Test
-    public void notifyTracksChanged() {
-        List<TvTrackInfo> tracks =
-                ImmutableList.of(new TvTrackInfo.Builder(TvTrackInfo.TYPE_VIDEO, "test").build());
-        testSession.notifyTracksChanged(tracks);
-        assertThat(testCallback.tracks).isEqualTo(tracks);
-    }
-
-    @Test
-    public void notifyTrackSelected() {
-        testSession.notifyTrackSelected(TvTrackInfo.TYPE_AUDIO, "audio_test");
-        assertThat(testCallback.trackSelected)
-                .isEqualTo(Pair.create(TvTrackInfo.TYPE_AUDIO, "audio_test"));
-    }
-
-    @Test
-    public void notifyVideoAvailable() {
-        testSession.notifyVideoAvailable();
-        assertThat(testCallback.videoAvailable).isTrue();
-    }
-
-    @Test
-    public void notifyVideoUnavailable() {
-        testSession.notifyVideoUnavailable(TvInputManager.VIDEO_UNAVAILABLE_REASON_UNKNOWN);
-        assertThat(testCallback.notifyVideoUnavailableReason)
-                .isEqualTo(TvInputManager.VIDEO_UNAVAILABLE_REASON_UNKNOWN);
-    }
-
-    @Test
-    public void notifyContentAllowed() {
-        testSession.notifyContentAllowed();
-        assertThat(testCallback.contentAllowed).isTrue();
-    }
-
-    @Test
-    public void notifyContentBlocked() {
-        TvContentRating rating = TvContentRating.createRating("1", "2", "3");
-        testSession.notifyContentBlocked(rating);
-        assertThat(testCallback.blockedContentRating).isEqualTo(rating);
-    }
-
-    @Test
-    public void notifyTimeShiftStatusChanged() {
-        testSession.notifyTimeShiftStatusChanged(TvInputManager.TIME_SHIFT_STATUS_AVAILABLE);
-        assertThat(testCallback.timeShiftStatus)
-                .isEqualTo(TvInputManager.TIME_SHIFT_STATUS_AVAILABLE);
-    }
-
-    @Test
-    public void testSetOverlayViewEnabled() {
-        testSession.helpTestSetOverlayViewEnabled(true);
-        assertThat(testCallback.overlayViewEnabled).isTrue();
-
-        testSession.helpTestSetOverlayViewEnabled(false);
-        assertThat(testCallback.overlayViewEnabled).isFalse();
-    }
-
-    @Test
-    public void testOnCreateOverlayView() {
-        View actualView = testSession.onCreateOverlayView();
-        assertThat(actualView).isNull(); // Default implementation returns a null.
-    }
-
-    @Test
-    public void testOnOverlayViewSizeChanged() {
-        testSession.onOverlayViewSizeChanged(5 /* width */, 7 /* height */);
-        // Just verifing that the call completes.
-    }
-
-    private static final class TestCallback implements TifSessionCallbacks {
-
-        private Uri channelUri;
-        private List<TvTrackInfo> tracks;
-        private Pair<Integer, String> trackSelected;
-        private boolean videoAvailable;
-        private int notifyVideoUnavailableReason;
-        private boolean contentAllowed;
-        private TvContentRating blockedContentRating;
-        private int timeShiftStatus;
-        private boolean overlayViewEnabled;
-
-        @Override
-        public void notifyChannelRetuned(Uri channelUri) {
-            this.channelUri = channelUri;
-        }
-
-        @Override
-        public void notifyTracksChanged(List<TvTrackInfo> tracks) {
-            this.tracks = tracks;
-        }
-
-        @Override
-        public void notifyTrackSelected(int type, String trackId) {
-            this.trackSelected = Pair.create(type, trackId);
-        }
-
-        @Override
-        public void notifyVideoAvailable() {
-            this.videoAvailable = true;
-        }
-
-        @Override
-        public void notifyVideoUnavailable(int reason) {
-            this.notifyVideoUnavailableReason = reason;
-        }
-
-        @Override
-        public void notifyContentAllowed() {
-            this.contentAllowed = true;
-        }
-
-        @Override
-        public void notifyContentBlocked(@NonNull TvContentRating rating) {
-            this.blockedContentRating = rating;
-        }
-
-        @Override
-        public void notifyTimeShiftStatusChanged(int status) {
-            this.timeShiftStatus = status;
-        }
-
-        @Override
-        public void setOverlayViewEnabled(boolean enabled) {
-            this.overlayViewEnabled = enabled;
-        }
-    }
-
-    private static final class TestSession extends TifSession {
-
-        private TestSession(TifSessionCallbacks callbacks) {
-            super(callbacks);
-        }
-
-        @Override
-        public boolean onSetSurface(@Nullable Surface surface) {
-            return false;
-        }
-
-        @Override
-        public void onSurfaceChanged(int format, int width, int height) {}
-
-        @Override
-        public void onSetStreamVolume(@FloatRange(from = 0.0, to = 1.0) float volume) {}
-
-        @Override
-        public boolean onTune(Uri channelUri) {
-            return false;
-        }
-
-        @Override
-        public void onSetCaptionEnabled(boolean enabled) {}
-
-        @Override
-        public void onUnblockContent(TvContentRating unblockedRating) {}
-
-        public void helpTestSetOverlayViewEnabled(boolean enabled) {
-            super.setOverlayViewEnabled(enabled);
-        }
-    }
-}
diff --git a/common/tests/robotests/src/com/android/tv/common/support/tis/WrappedSessionTest.java b/common/tests/robotests/src/com/android/tv/common/support/tis/WrappedSessionTest.java
deleted file mode 100644
index f5b6146..0000000
--- a/common/tests/robotests/src/com/android/tv/common/support/tis/WrappedSessionTest.java
+++ /dev/null
@@ -1,190 +0,0 @@
-package com.android.tv.common.support.tis;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.media.PlaybackParams;
-import android.media.tv.TvContentRating;
-import android.net.Uri;
-import android.os.Build;
-import android.view.View;
-
-import com.android.tv.common.support.tis.TifSession.TifSessionCallbacks;
-import com.android.tv.common.support.tis.TifSession.TifSessionFactory;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-/** Tests for {@link WrappedSession}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(minSdk = Build.VERSION_CODES.M, maxSdk = Build.VERSION_CODES.P)
-public class WrappedSessionTest {
-
-    @Mock TifSession mockDelegate;
-    private TifSessionFactory sessionFactory =
-            new TifSessionFactory() {
-                @Override
-                public TifSession create(TifSessionCallbacks callbacks, String inputId) {
-                    return mockDelegate;
-                }
-            };
-    private WrappedSession wrappedSession;
-    private SimpleSessionManager sessionManager = new SimpleSessionManager(1);
-
-    @Before
-    public void setup() {
-        MockitoAnnotations.initMocks(this);
-        wrappedSession =
-                new WrappedSession(
-                        RuntimeEnvironment.application,
-                        sessionManager,
-                        sessionFactory,
-                        "testInputId");
-    }
-
-    @Test
-    public void onRelease() {
-        sessionManager.addSession(wrappedSession);
-        assertThat(sessionManager.getSessionCount()).isEqualTo(1);
-        wrappedSession.onRelease();
-        assertThat(sessionManager.getSessionCount()).isEqualTo(0);
-        Mockito.verify(mockDelegate).onRelease();
-        Mockito.verifyNoMoreInteractions(mockDelegate);
-    }
-
-    @Test
-    public void onSetSurface() {
-        wrappedSession.onSetSurface(null);
-        Mockito.verify(mockDelegate).onSetSurface(null);
-        Mockito.verifyNoMoreInteractions(mockDelegate);
-    }
-
-    @Test
-    public void onSurfaceChanged() {
-        wrappedSession.onSurfaceChanged(1, 2, 3);
-        Mockito.verify(mockDelegate).onSurfaceChanged(1, 2, 3);
-        Mockito.verifyNoMoreInteractions(mockDelegate);
-    }
-
-    @Test
-    public void onSetStreamVolume() {
-        wrappedSession.onSetStreamVolume(.8f);
-        Mockito.verify(mockDelegate).onSetStreamVolume(.8f);
-        Mockito.verifyNoMoreInteractions(mockDelegate);
-    }
-
-    @Test
-    public void onTune() {
-        Uri uri = Uri.EMPTY;
-        wrappedSession.onTune(uri);
-        Mockito.verify(mockDelegate).onTune(uri);
-        Mockito.verifyNoMoreInteractions(mockDelegate);
-    }
-
-    @Test
-    public void onSetCaptionEnabled() {
-        wrappedSession.onSetCaptionEnabled(true);
-        Mockito.verify(mockDelegate).onSetCaptionEnabled(true);
-        Mockito.verifyNoMoreInteractions(mockDelegate);
-    }
-
-    @Test
-    @Config(minSdk = Build.VERSION_CODES.M)
-    public void onTimeShiftGetCurrentPosition() {
-        Mockito.when(mockDelegate.onTimeShiftGetCurrentPosition()).thenReturn(7L);
-        assertThat(wrappedSession.onTimeShiftGetCurrentPosition()).isEqualTo(7L);
-        Mockito.verify(mockDelegate).onTimeShiftGetCurrentPosition();
-        Mockito.verifyNoMoreInteractions(mockDelegate);
-    }
-
-    @Test
-    @Config(minSdk = Build.VERSION_CODES.M)
-    public void onTimeShiftGetStartPosition() {
-        Mockito.when(mockDelegate.onTimeShiftGetStartPosition()).thenReturn(8L);
-        assertThat(wrappedSession.onTimeShiftGetStartPosition()).isEqualTo(8L);
-        Mockito.verify(mockDelegate).onTimeShiftGetStartPosition();
-        Mockito.verifyNoMoreInteractions(mockDelegate);
-    }
-
-    @Test
-    @Config(minSdk = Build.VERSION_CODES.M)
-    public void onTimeShiftPause() {
-        wrappedSession.onTimeShiftPause();
-        Mockito.verify(mockDelegate).onTimeShiftPause();
-        Mockito.verifyNoMoreInteractions(mockDelegate);
-    }
-
-    @Test
-    @Config(minSdk = Build.VERSION_CODES.M)
-    public void onTimeShiftResume() {
-        wrappedSession.onTimeShiftResume();
-        Mockito.verify(mockDelegate).onTimeShiftResume();
-        Mockito.verifyNoMoreInteractions(mockDelegate);
-    }
-
-    @Test
-    @Config(minSdk = Build.VERSION_CODES.M)
-    public void onTimeShiftSeekTo() {
-        wrappedSession.onTimeShiftSeekTo(9L);
-        Mockito.verify(mockDelegate).onTimeShiftSeekTo(9L);
-        Mockito.verifyNoMoreInteractions(mockDelegate);
-    }
-
-    @Test
-    @Config(minSdk = Build.VERSION_CODES.M)
-    public void onTimeShiftSetPlaybackParams() {
-        PlaybackParams paras = new PlaybackParams();
-        wrappedSession.onTimeShiftSetPlaybackParams(paras);
-        Mockito.verify(mockDelegate).onTimeShiftSetPlaybackParams(paras);
-        Mockito.verifyNoMoreInteractions(mockDelegate);
-    }
-
-    @Test
-    @Config(minSdk = Build.VERSION_CODES.M)
-    public void onUnblockContent() {
-        TvContentRating rating =
-                TvContentRating.createRating(
-                        "domain", "rating_system", "rating", "subrating1", "subrating2");
-        wrappedSession.onUnblockContent(rating);
-        Mockito.verify(mockDelegate).onUnblockContent(rating);
-        Mockito.verifyNoMoreInteractions(mockDelegate);
-    }
-
-    @Test
-    public void onParentalControlsChanged() {
-        wrappedSession.onParentalControlsChanged();
-        Mockito.verify(mockDelegate).onParentalControlsChanged();
-        Mockito.verifyNoMoreInteractions(mockDelegate);
-    }
-
-    @Test
-    public void testSetOverlayViewEnabled() {
-        wrappedSession.setOverlayViewEnabled(true);
-        // Just verifying that the call completes.
-    }
-
-    @Test
-    public void testOnCreateOverlayView() {
-        View v = new View(RuntimeEnvironment.application);
-        Mockito.when(mockDelegate.onCreateOverlayView()).thenReturn(v);
-
-        View actualView = wrappedSession.onCreateOverlayView();
-
-        assertThat(actualView).isEqualTo(v);
-        Mockito.verify(mockDelegate).onCreateOverlayView();
-        Mockito.verifyNoMoreInteractions(mockDelegate);
-    }
-
-    @Test
-    public void testOnOverlayViewSizeChanged() {
-        wrappedSession.onOverlayViewSizeChanged(5 /* width */, 13 /* height */);
-        Mockito.verify(mockDelegate).onOverlayViewSizeChanged(5, 13);
-        Mockito.verifyNoMoreInteractions(mockDelegate);
-    }
-}
diff --git a/common/tests/robotests/src/com/android/tv/common/support/tvprovider/TvContractCompatXTest.java b/common/tests/robotests/src/com/android/tv/common/support/tvprovider/TvContractCompatXTest.java
deleted file mode 100644
index 51cc19d..0000000
--- a/common/tests/robotests/src/com/android/tv/common/support/tvprovider/TvContractCompatXTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2019 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.support.tvprovider;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.net.Uri;
-
-import com.android.tv.testing.constants.ConfigConstants;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-/** Test for {@link TvContractCompatX}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-public class TvContractCompatXTest {
-
-    @Test
-    public void buildChannelUri() {
-        assertThat(TvContractCompatX.buildChannelUri("com.example", "foo"))
-                .isEqualTo(
-                        Uri.parse(
-                                "content://android.media.tv/channel?"
-                                        + "package=com.example&internal_provider_id=foo"));
-    }
-
-    @Test
-    public void buildProgramsUriForChannel() {
-        assertThat(TvContractCompatX.buildProgramsUriForChannel("com.example", "foo"))
-                .isEqualTo(
-                        Uri.parse(
-                                "content://android.media.tv/program?"
-                                        + "package=com.example&internal_provider_id=foo"));
-    }
-
-    @Test
-    public void buildProgramsUriForChannel_period() {
-        assertThat(TvContractCompatX.buildProgramsUriForChannel("com.example", "foo", 1234L, 5467L))
-                .isEqualTo(
-                        Uri.parse(
-                                "content://android.media.tv/program?"
-                                        + "package=com.example&internal_provider_id=foo"
-                                        + "&start_time=1234&end_time=5467"));
-    }
-
-    @Test
-    public void buildProgramsUri_period() {
-        assertThat(TvContractCompatX.buildProgramsUri(1234L, 5467L))
-                .isEqualTo(
-                        Uri.parse(
-                                "content://android.media.tv/program?"
-                                        + "start_time=1234&end_time=5467"));
-    }
-}
diff --git a/common/tests/robotests/src/com/android/tv/common/util/CommonUtilsTest.java b/common/tests/robotests/src/com/android/tv/common/util/CommonUtilsTest.java
deleted file mode 100644
index 3930ff6..0000000
--- a/common/tests/robotests/src/com/android/tv/common/util/CommonUtilsTest.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2018 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.util;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import com.android.tv.testing.constants.ConfigConstants;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-import java.io.File;
-import java.io.IOException;
-
-/** Tests for {@link CommonUtils}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-public class CommonUtilsTest {
-
-    @Test
-    public void deleteDirOrFile_file() throws IOException {
-        File file = new File(RuntimeEnvironment.application.getExternalFilesDir(null), "file");
-        assertThat(file.createNewFile()).isTrue();
-        assertThat(CommonUtils.deleteDirOrFile(file)).isTrue();
-        assertThat(file.exists()).isFalse();
-    }
-
-    @Test
-    public void deleteDirOrFile_Dir() throws IOException {
-        File dir = new File(RuntimeEnvironment.application.getExternalFilesDir(null), "dir");
-        assertThat(dir.mkdirs()).isTrue();
-        assertThat(new File(dir, "file").createNewFile()).isTrue();
-        assertThat(CommonUtils.deleteDirOrFile(dir)).isTrue();
-        assertThat(dir.exists()).isFalse();
-    }
-
-    @Test
-    public void deleteDirOrFile_unreadableDir() throws IOException {
-        File dir = new File(RuntimeEnvironment.application.getExternalFilesDir(null), "dir");
-        assertThat(dir.mkdirs()).isTrue();
-        assertThat(new File(dir, "file").createNewFile()).isTrue();
-        dir.setReadable(false);
-        // Since dir is unreadable dir.listFiles() returns null and file is not deleted thus
-        // dir is not actually deleted.
-        assertThat(CommonUtils.deleteDirOrFile(dir)).isFalse();
-        assertThat(dir.exists()).isTrue();
-    }
-
-    @Test
-    public void deleteDirOrFile_unreadableSubDir() throws IOException {
-        File dir = new File(RuntimeEnvironment.application.getExternalFilesDir(null), "dir");
-        File subDir = new File(dir, "sub");
-        assertThat(subDir.mkdirs()).isTrue();
-        File file = new File(subDir, "file");
-        assertThat(file.createNewFile()).isTrue();
-        subDir.setReadable(false);
-        // Since subDir is unreadable subDir.listFiles() returns null and file is not deleted thus
-        // dir is not actually deleted.
-        assertThat(CommonUtils.deleteDirOrFile(dir)).isFalse();
-        assertThat(dir.exists()).isTrue();
-    }
-}
diff --git a/common/tests/robotests/src/com/android/tv/common/util/ContentUriUtilsTest.java b/common/tests/robotests/src/com/android/tv/common/util/ContentUriUtilsTest.java
deleted file mode 100644
index 5828672..0000000
--- a/common/tests/robotests/src/com/android/tv/common/util/ContentUriUtilsTest.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2018 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.util;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.net.Uri;
-
-import com.android.tv.testing.constants.ConfigConstants;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-/** Tests for {@link ContentUriUtils}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-public class ContentUriUtilsTest {
-
-    @Test
-    public void safeParseId_empty() {
-        assertThat(ContentUriUtils.safeParseId(Uri.EMPTY)).isEqualTo(-1);
-    }
-
-    @Test
-    public void safeParseId_bad() {
-        assertThat(ContentUriUtils.safeParseId(Uri.parse("foo/bad"))).isEqualTo(-1);
-    }
-
-    @Test
-    public void safeParseId_123() {
-        assertThat(ContentUriUtils.safeParseId(Uri.parse("foo/123"))).isEqualTo(123);
-    }
-}
diff --git a/gradle.properties b/gradle.properties
index 9d027fe..6208234 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -21,5 +21,4 @@
 
 org.gradle.daemon=true
 org.gradle.parallel=true
-android.useAndroidX=true
-android.enableJetifier=true
\ No newline at end of file
+org.gradle.configureondemand=true
\ No newline at end of file
diff --git a/jni/DvbManager.cpp b/jni/DvbManager.cpp
index 3320959..f9dff59 100644
--- a/jni/DvbManager.cpp
+++ b/jni/DvbManager.cpp
@@ -42,6 +42,7 @@
           mDvrFd(-1),
           mPatFilterFd(-1),
           mDvbApiVersion(DVB_API_VERSION_UNDEFINED),
+          mDeliverySystemType(-1),
           mFeHasLock(false),
           mHasPendingTune(false) {
   jclass clazz = env->FindClass("com/android/tv/tuner/TunerHal");
@@ -49,8 +50,6 @@
       env->GetMethodID(clazz, "openDvbFrontEndFd", "()I");
   mOpenDvbDemuxMethodID = env->GetMethodID(clazz, "openDvbDemuxFd", "()I");
   mOpenDvbDvrMethodID = env->GetMethodID(clazz, "openDvbDvrFd", "()I");
-  memset(&mDeliverySystemTypes, DELIVERY_SYSTEM_UNDEFINED,
-      sizeof(mDeliverySystemTypes));
 }
 
 DvbManager::~DvbManager() {
@@ -116,20 +115,6 @@
 
 int DvbManager::tune(JNIEnv *env, jobject thiz,
         const int frequency, const char *modulationStr, int timeout_ms) {
-    return tuneInternal(env, thiz, DELIVERY_SYSTEM_UNDEFINED, frequency,
-               modulationStr, timeout_ms);
-}
-
-int DvbManager::tune(JNIEnv *env, jobject thiz,
-        const int deliverySystemType, const int frequency,
-        const char *modulationStr, int timeout_ms) {
-    return tuneInternal(env, thiz, deliverySystemType, frequency,
-               modulationStr, timeout_ms);
-}
-
-int DvbManager::tuneInternal(JNIEnv *env, jobject thiz,
-        const int deliverySystemType, const int frequency,
-        const char *modulationStr, int timeout_ms) {
     resetExceptFe();
 
     if (openDvbFe(env, thiz) != 0) {
@@ -161,36 +146,10 @@
         struct dtv_property deliverySystemProperty = {
             .cmd = DTV_DELIVERY_SYSTEM
         };
-        switch (deliverySystemType) {
-            case DELIVERY_SYSTEM_DVBT:
-                deliverySystemProperty.u.data = SYS_DVBT;
-                break;
-            case DELIVERY_SYSTEM_DVBT2:
-                deliverySystemProperty.u.data = SYS_DVBT2;
-                break;
-            case DELIVERY_SYSTEM_DVBS:
-                deliverySystemProperty.u.data = SYS_DVBS;
-                break;
-            case DELIVERY_SYSTEM_DVBS2:
-                deliverySystemProperty.u.data = SYS_DVBS2;
-                break;
-            case DELIVERY_SYSTEM_DVBC:
-                deliverySystemProperty.u.data = SYS_DVBC_ANNEX_A;
-                break;
-            case DELIVERY_SYSTEM_ATSC:
-            case DELIVERY_SYSTEM_UNDEFINED:
-                deliverySystemProperty.u.data = SYS_ATSC;
-                break;
-            default:
-                ALOGE("Unrecognized delivery system type");
-                return -1;
-        }
+        deliverySystemProperty.u.data = SYS_ATSC;
         struct dtv_property frequencyProperty = {
             .cmd = DTV_FREQUENCY
         };
-        struct dtv_property bandwidthProperty = {
-             .cmd = DTV_BANDWIDTH_HZ, .u.data = 8000000
-        };
         frequencyProperty.u.data = static_cast<__u32>(frequency);
         struct dtv_property modulationProperty = { .cmd = DTV_MODULATION };
         if (strncmp(modulationStr, "QAM", 3) == 0) {
@@ -204,11 +163,10 @@
         struct dtv_property tuneProperty = { .cmd = DTV_TUNE };
 
         struct dtv_property props[] = {
-                deliverySystemProperty, frequencyProperty, modulationProperty,
-                bandwidthProperty, tuneProperty
+                deliverySystemProperty, frequencyProperty, modulationProperty, tuneProperty
         };
         struct dtv_properties dtvProperty = {
-            .num = sizeof(props)/sizeof(dtv_property), .props = props
+            .num = 4, .props = props
         };
 
         if (mHasPendingTune) {
@@ -257,9 +215,6 @@
                     ALOGE("Unrecognized modulation mode : %s", modulationStr);
                     return -1;
                 }
-                feParams.u.ofdm.code_rate_HP = FEC_AUTO;
-                feParams.u.ofdm.code_rate_LP = FEC_AUTO;
-                feParams.u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO;
                 break;
             default:
                 ALOGE("Unsupported delivery system.");
@@ -507,27 +462,22 @@
 }
 
 int DvbManager::getDeliverySystemType(JNIEnv *env, jobject thiz) {
-    getDeliverySystemTypes(env, thiz);
-    return mDeliverySystemTypes[0];
-}
-
-int* DvbManager::getDeliverySystemTypes(JNIEnv *env, jobject thiz) {
-    ALOGE("getDeliverySystemTypes");
-    if (mDeliverySystemTypes[0] != DELIVERY_SYSTEM_UNDEFINED) {
-        return mDeliverySystemTypes;
+    if (mDeliverySystemType != -1) {
+        return mDeliverySystemType;
     }
     if (mFeFd == -1) {
         if ((mFeFd = openDvbFeFromSystemApi(env, thiz)) < 0) {
             ALOGD("Can't open FE file : %s", strerror(errno));
-            return mDeliverySystemTypes;
+            return DELIVERY_SYSTEM_UNDEFINED;
         }
     }
     struct dtv_property testProps[1] = {
-        { .cmd = DTV_ENUM_DELSYS }
+        { .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) {
@@ -535,52 +485,50 @@
             if (ioctl(mFeFd, FE_GET_INFO, &info) == 0) {
                 switch (info.type) {
                     case FE_QPSK:
-                        mDeliverySystemTypes[0] = DELIVERY_SYSTEM_DVBS;
+                        mDeliverySystemType = DELIVERY_SYSTEM_DVBS;
                         break;
                     case FE_QAM:
-                        mDeliverySystemTypes[0] = DELIVERY_SYSTEM_DVBC;
+                        mDeliverySystemType = DELIVERY_SYSTEM_DVBC;
                         break;
                     case FE_OFDM:
-                        mDeliverySystemTypes[0] = DELIVERY_SYSTEM_DVBT;
+                        mDeliverySystemType = DELIVERY_SYSTEM_DVBT;
                         break;
                     case FE_ATSC:
-                        mDeliverySystemTypes[0] = DELIVERY_SYSTEM_ATSC;
+                        mDeliverySystemType = DELIVERY_SYSTEM_ATSC;
                         break;
                     default:
-                        mDeliverySystemTypes[0] = DELIVERY_SYSTEM_UNDEFINED;
+                        mDeliverySystemType = DELIVERY_SYSTEM_UNDEFINED;
                         break;
                 }
             }
         }
     } else {
         mDvbApiVersion = DVB_API_VERSION5;
-        for (unsigned int i = 0; i < feProp.props[0].u.buffer.len; i++) {
-            switch (feProp.props[0].u.buffer.data[i]) {
-                case SYS_DVBT:
-                    mDeliverySystemTypes[i] = DELIVERY_SYSTEM_DVBT;
-                    break;
-                case SYS_DVBT2:
-                    mDeliverySystemTypes[i] = DELIVERY_SYSTEM_DVBT2;
-                    break;
-                case SYS_DVBS:
-                    mDeliverySystemTypes[i] = DELIVERY_SYSTEM_DVBS;
-                    break;
-                case SYS_DVBS2:
-                    mDeliverySystemTypes[i] = DELIVERY_SYSTEM_DVBS2;
-                    break;
-                case SYS_DVBC_ANNEX_A:
-                case SYS_DVBC_ANNEX_B:
-                case SYS_DVBC_ANNEX_C:
-                    mDeliverySystemTypes[i] = DELIVERY_SYSTEM_DVBC;
-                    break;
-                case SYS_ATSC:
-                    mDeliverySystemTypes[i] = DELIVERY_SYSTEM_ATSC;
-                    break;
-                default:
-                    mDeliverySystemTypes[i] = DELIVERY_SYSTEM_UNDEFINED;
-                    break;
-            }
+        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 mDeliverySystemTypes;
-}
+    return mDeliverySystemType;
+}
\ No newline at end of file
diff --git a/jni/DvbManager.h b/jni/DvbManager.h
index aaa345e..b01113e 100644
--- a/jni/DvbManager.h
+++ b/jni/DvbManager.h
@@ -63,7 +63,7 @@
     int mDvrFd;
     int mPatFilterFd;
     int mDvbApiVersion;
-    int mDeliverySystemTypes[8];
+    int mDeliverySystemType;
     bool mFeHasLock;
     // Flag for pending tune request. Used for canceling the current tune operation.
     bool volatile mHasPendingTune;
@@ -78,9 +78,6 @@
     ~DvbManager();
     int tune(JNIEnv *env, jobject thiz,
             const int frequency, const char *modulationStr, int timeout_ms);
-    int tune(JNIEnv *env, jobject thiz,
-            const int deliverySystemType, const int frequency,
-            const char *modulationStr, int timeout_ms);
     int stopTune();
     int readTsStream(JNIEnv *env, jobject thiz,
             uint8_t *tsBuffer, int tsBufferSize, int timeout_ms);
@@ -88,13 +85,9 @@
     void closeAllDvbPidFilter();
     void setHasPendingTune(bool hasPendingTune);
     int getDeliverySystemType(JNIEnv *env, jobject thiz);
-    int *getDeliverySystemTypes(JNIEnv *env, jobject thiz);
     int getSignalStrength();
 
 private:
-    int tuneInternal(JNIEnv *env, jobject thiz,
-            const int deliverySystemType, const int frequency,
-            const char *modulationStr, int timeout_ms);
     int openDvbFe(JNIEnv *env, jobject thiz);
     int openDvbDvr(JNIEnv *env, jobject thiz);
     void closePatFilter();
diff --git a/jni/tunertvinput_jni.cpp b/jni/tunertvinput_jni.cpp
index 579b92e..030f961 100644
--- a/jni/tunertvinput_jni.cpp
+++ b/jni/tunertvinput_jni.cpp
@@ -49,12 +49,11 @@
 /*
  * Class:     com_android_tv_tuner_TunerHal
  * Method:    nativeTune
- * Signature: (JILjava/lang/String;I)Z
+ * Signature: (JILjava/lang/String;)Z
  */
-JNIEXPORT jboolean JNICALL
-    Java_com_android_tv_tuner_TunerHal_nativeTune__JILjava_lang_String_2I(
-        JNIEnv *env, jobject thiz, jlong deviceId, jint frequency,
-        jstring modulation, jint timeout_ms) {
+JNIEXPORT jboolean JNICALL Java_com_android_tv_tuner_TunerHal_nativeTune(
+    JNIEnv *env, jobject thiz, jlong deviceId, jint frequency,
+    jstring modulation, jint timeout_ms) {
   std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
   DvbManager *dvbManager;
   if (it == sDvbManagers.end()) {
@@ -70,29 +69,6 @@
 
 /*
  * Class:     com_android_tv_tuner_TunerHal
- * Method:    nativeTune
- * Signature: (JIILjava/lang/String;I)Z
- */
-JNIEXPORT jboolean JNICALL
-    Java_com_android_tv_tuner_TunerHal_nativeTune__JIILjava_lang_String_2I(
-        JNIEnv *env, jobject thiz, jlong deviceId, jint deliverySystemType,
-        jint frequency, jstring modulation, jint timeout_ms) {
-    std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
-    DvbManager *dvbManager;
-    if (it == sDvbManagers.end()) {
-        dvbManager = new DvbManager(env, thiz);
-        sDvbManagers.insert(
-            std::pair<jlong, DvbManager *>(deviceId, dvbManager));
-    } else {
-        dvbManager = it->second;
-    }
-    int res = dvbManager->tune(env, thiz, deliverySystemType, frequency,
-                env->GetStringUTFChars(modulation, 0), timeout_ms);
-    return (res == 0);
-}
-
-/*
- * Class:     com_android_tv_tuner_TunerHal
  * Method:    nativeCloseAllPidFilters
  * Signature: (J)V
  */
@@ -214,32 +190,4 @@
     sDvbManagers.insert(std::pair<jlong, DvbManager *>(deviceId, dvbManager));
     return dvbManager->getDeliverySystemType(env, thiz);
   }
-}
-
-/*
- * Class:     com_android_tv_tuner_TunerHal
- * Method:    nativeGetDeliverySystemTypes
- * Signature: (J)I
- */
-JNIEXPORT jintArray JNICALL
-Java_com_android_tv_tuner_TunerHal_nativeGetDeliverySystemTypes(JNIEnv *env,
-                                                               jobject thiz,
-                                                               jlong deviceId) {
-    jintArray deliverySystemTypes = env->NewIntArray(8);
-    if (deliverySystemTypes == NULL) {
-        ALOGE("Out of memory!");
-        return NULL;
-    }
-    std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
-    if (it != sDvbManagers.end()) {
-        env->SetIntArrayRegion(deliverySystemTypes, 0, 8,
-        it->second->getDeliverySystemTypes(env, thiz));
-    } else {
-        DvbManager *dvbManager = new DvbManager(env, thiz);
-        sDvbManagers.insert(
-            std::pair<jlong, DvbManager *>(deviceId, dvbManager));
-        env->SetIntArrayRegion(deliverySystemTypes, 0, 8,
-        dvbManager->getDeliverySystemTypes(env, thiz));
-    }
-    return deliverySystemTypes;
-}
+}
\ No newline at end of file
diff --git a/jni/tunertvinput_jni.h b/jni/tunertvinput_jni.h
index 02c242b..36e631f 100755
--- a/jni/tunertvinput_jni.h
+++ b/jni/tunertvinput_jni.h
@@ -66,18 +66,8 @@
  * Method:    nativeTune
  * Signature: (JILjava/lang/String;I)Z
  */
-JNIEXPORT jboolean JNICALL
-    Java_com_android_tv_tuner_TunerHal_nativeTune__JILjava_lang_String_2I
-        (JNIEnv *, jobject, jlong, jint, jstring, jint);
-
-/*
- * Class:     com_android_tv_tuner_TunerHal
- * Method:    nativeTune
- * Signature: Signature: (JIILjava/lang/String;I)Z
- */
-JNIEXPORT jboolean JNICALL
-    Java_com_android_tv_tuner_TunerHal_nativeTune__JIILjava_lang_String_2I
-        (JNIEnv *, jobject, jlong, jint, jint, jstring, jint);
+JNIEXPORT jboolean JNICALL Java_com_android_tv_tuner_TunerHal_nativeTune
+  (JNIEnv *, jobject, jlong, jint, jstring, jint);
 
 /*
  * Class:     com_android_tv_tuner_TunerHal
@@ -116,15 +106,6 @@
 
 /*
  * Class:     com_android_tv_tuner_TunerHal
- * Method:    nativeGetDeliverySystemTypes
- * Signature: (J)I
- */
-JNIEXPORT jintArray JNICALL
-Java_com_android_tv_tuner_TunerHal_nativeGetDeliverySystemTypes
-  (JNIEnv *, jobject, jlong);
-
-/*
- * Class:     com_android_tv_tuner_TunerHal
  * Method:    nativeGetSignalStrength
  * Signature: (J)I
  */
diff --git a/libs/Android.bp b/libs/Android.bp
index 7c41f4e..fea9487 100644
--- a/libs/Android.bp
+++ b/libs/Android.bp
@@ -13,15 +13,8 @@
 // limitations under the License.
 
 java_import {
-    name: "tv-auto-common-jar",
-    jars: ["m2/auto-common-0.10.jar"],
-    host_supported: true,
-    sdk_version: "current",
-}
-
-java_import {
     name: "tv-auto-factory-jar",
-    jars: ["m2/auto-factory-1.0-beta6.jar"],
+    jars: ["auto-factory-1.0-beta2.jar"],
     host_supported: true,
     sdk_version: "current",
 }
@@ -29,22 +22,20 @@
 java_plugin {
     name: "tv-auto-factory",
     static_libs: [
-        "jsr330",
-        "tv-auto-common-jar",
+	"jsr330",
         "tv-auto-factory-jar",
-        "tv-auto-value-jar",
-        "tv-google-java-format-jar",
         "tv-guava-jre-jar",
-        "tv-javapoet-jar",
-        "tv-javax-annotations-jar",
+	"tv-javawriter-jar",
+	"tv-javax-annotations-jar",
     ],
     processor_class: "com.google.auto.factory.processor.AutoFactoryProcessor",
     generates_api: true,
 }
 
+
 java_import {
     name: "tv-auto-value-jar",
-    jars: ["m2/auto-value-1.5.3.jar"],
+    jars: ["auto-value-1.5.2.jar"],
     host_supported: true,
     sdk_version: "current",
 }
@@ -60,40 +51,26 @@
 
 java_import {
     name: "tv-error-prone-annotations-jar",
-    jars: ["m2/error_prone_annotations-2.3.2.jar"],
+    jars: ["error_prone_annotations-2.3.1.jar"],
     sdk_version: "current",
 }
 
 java_import {
-    name: "tv-google-java-format-jar",
-    jars: ["google-java-format-1.7-all-deps.jar"],
+    name: "tv-guava-jre-jar",
+    jars: ["guava-23.3-jre.jar"],
     host_supported: true,
     sdk_version: "current",
 }
 
 java_import {
     name: "tv-guava-android-jar",
-    jars: ["m2/guava-28.0-android.jar"],
+    jars: ["guava-23.6-android.jar"],
     sdk_version: "current",
 }
 
-java_import {
-    name: "tv-guava-jre-jar",
-    jars: ["m2/guava-28.0-jre.jar"],
-    host_supported: true,
-    sdk_version: "current",
-}
-
-java_import {
-    name: "tv-guava-failureaccess-jar",
-    jars: ["m2/failureaccess-1.0.1.jar"],
-    host_supported: true,
-    sdk_version: "current",
-}
-
-java_import_host {
-    name: "tv-javapoet-jar",
-    jars: ["m2/javapoet-1.11.1.jar"],
+java_import_host{
+    name: "tv-javawriter-jar",
+    jars: ["javawriter-2.5.1.jar"],
 }
 
 java_import {
@@ -103,6 +80,7 @@
     sdk_version: "current",
 }
 
+
 android_library_import {
     name: "tv-lib-exoplayer",
     aars: ["exoplayer-r1.5.16.aar"],
@@ -111,22 +89,31 @@
 
 android_library_import {
     name: "tv-lib-exoplayer-v2-core",
-    aars: ["exoplayer-core-2.10.1.aar"],
+    aars: ["exoplayer-core-2.9.0.aar"],
     sdk_version: "current",
 }
 
 java_import_host {
+    name: "tv-lib-dagger-compiler-deps",
+    jars: [
+        "google-java-format-1.4-all-deps.jar",
+        "guava-23.3-jre.jar",
+        "javapoet-1.8.0.jar",
+    ],
+}
+
+java_import_host {
     name: "tv-lib-dagger-compiler-import",
     jars: [
-        "m2/dagger-compiler-2.23.jar",
-        "m2/dagger-producers-2.23.jar",
-        "m2/dagger-spi-2.23.jar",
+        "dagger-compiler-2.15.jar",
+        "dagger-producers-2.15.jar",
+        "dagger-spi-2.15.jar",
     ],
 }
 
 java_import {
     name: "tv-lib-dagger",
-    jars: ["m2/dagger-2.23.jar"],
+    jars: ["dagger-2.15.jar"],
     host_supported: true,
     sdk_version: "current",
 }
@@ -135,30 +122,26 @@
     name: "tv-lib-dagger-compiler",
     static_libs: [
         "tv-lib-dagger-compiler-import",
-        "tv-guava-jre-jar",
-        "tv-javapoet-jar",
+        "tv-lib-dagger-compiler-deps",
         "jsr330",
         "tv-lib-dagger",
     ],
     processor_class: "dagger.internal.codegen.ComponentProcessor",
     generates_api: true,
-      // shade guava to avoid conflicts with guava embedded in Error Prone.
-        jarjar_rules: "m2/dagger-jarjar-rules.txt",
 }
 
 android_library_import {
     name: "tv-lib-dagger-android",
-    aars: ["m2/dagger-android-2.23.aar"],
+    aars: ["dagger-android-2.15.aar"],
     sdk_version: "current",
 }
 
 java_import_host {
     name: "tv-lib-dagger-android-processor-import",
     jars: [
-        "m2/dagger-android-jarimpl-2.23.jar",
-        "m2/dagger-android-processor-2.23.jar",
-        "m2/dagger-spi-2.23.jar",
-        "m2/protobuf-java-3.7.0.jar",
+        "dagger-android-jarimpl-2.15.jar",
+        "dagger-android-processor-2.15.jar",
+        "dagger-android-support-jarimpl-2.15.jar",
     ],
 }
 
@@ -166,22 +149,17 @@
     name: "tv-lib-dagger-android-processor",
     static_libs: [
         "tv-lib-dagger-android-processor-import",
-        "tv-guava-jre-jar",
-        "tv-guava-failureaccess-jar",
-        "tv-javapoet-jar",
-        "tv-google-java-format-jar",
+        "tv-lib-dagger-compiler-deps",
         "jsr330",
         "tv-lib-dagger",
     ],
     processor_class: "dagger.android.processor.AndroidProcessor",
     generates_api: true,
-          // shade guava to avoid conflicts with guava embedded in Error Prone.
-            jarjar_rules: "m2/dagger-jarjar-rules.txt",
 }
 
 java_import {
     name: "tv-lib-truth",
-    jars: ["truth-0.45.jar"],
+    jars: ["truth-0.36.jar"],
     host_supported: true,
     sdk_version: "current",
 }
diff --git a/libs/auto-factory-1.0-beta2.jar b/libs/auto-factory-1.0-beta2.jar
new file mode 100644
index 0000000..ceaddac
--- /dev/null
+++ b/libs/auto-factory-1.0-beta2.jar
Binary files differ
diff --git a/libs/auto-value-1.5.2.jar b/libs/auto-value-1.5.2.jar
new file mode 100644
index 0000000..8ac0567
--- /dev/null
+++ b/libs/auto-value-1.5.2.jar
Binary files differ
diff --git a/libs/dagger-2.15.jar b/libs/dagger-2.15.jar
new file mode 100644
index 0000000..6d76688
--- /dev/null
+++ b/libs/dagger-2.15.jar
Binary files differ
diff --git a/libs/dagger-android-2.15.aar b/libs/dagger-android-2.15.aar
new file mode 100644
index 0000000..430294a
--- /dev/null
+++ b/libs/dagger-android-2.15.aar
Binary files differ
diff --git a/libs/dagger-android-jarimpl-2.15.jar b/libs/dagger-android-jarimpl-2.15.jar
new file mode 100644
index 0000000..7f7cd45
--- /dev/null
+++ b/libs/dagger-android-jarimpl-2.15.jar
Binary files differ
diff --git a/libs/dagger-android-processor-2.15.jar b/libs/dagger-android-processor-2.15.jar
new file mode 100644
index 0000000..3c7ac05
--- /dev/null
+++ b/libs/dagger-android-processor-2.15.jar
Binary files differ
diff --git a/libs/dagger-android-support-2.15.aar b/libs/dagger-android-support-2.15.aar
new file mode 100644
index 0000000..89a71a9
--- /dev/null
+++ b/libs/dagger-android-support-2.15.aar
Binary files differ
diff --git a/libs/dagger-android-support-jarimpl-2.15.jar b/libs/dagger-android-support-jarimpl-2.15.jar
new file mode 100644
index 0000000..d0ea01a
--- /dev/null
+++ b/libs/dagger-android-support-jarimpl-2.15.jar
Binary files differ
diff --git a/libs/dagger-compiler-2.15.jar b/libs/dagger-compiler-2.15.jar
new file mode 100644
index 0000000..e73110f
--- /dev/null
+++ b/libs/dagger-compiler-2.15.jar
Binary files differ
diff --git a/libs/dagger-producers-2.15.jar b/libs/dagger-producers-2.15.jar
new file mode 100644
index 0000000..f1dbb07
--- /dev/null
+++ b/libs/dagger-producers-2.15.jar
Binary files differ
diff --git a/libs/dagger-spi-2.15.jar b/libs/dagger-spi-2.15.jar
new file mode 100644
index 0000000..6e3156a
--- /dev/null
+++ b/libs/dagger-spi-2.15.jar
Binary files differ
diff --git a/libs/error_prone_annotations-2.3.1.jar b/libs/error_prone_annotations-2.3.1.jar
new file mode 100644
index 0000000..8a0efa3
--- /dev/null
+++ b/libs/error_prone_annotations-2.3.1.jar
Binary files differ
diff --git a/libs/exoplayer-core-2.10.1.aar b/libs/exoplayer-core-2.10.1.aar
deleted file mode 100644
index 2342fed..0000000
--- a/libs/exoplayer-core-2.10.1.aar
+++ /dev/null
Binary files differ
diff --git a/libs/exoplayer-core-2.9.0.aar b/libs/exoplayer-core-2.9.0.aar
new file mode 100644
index 0000000..64c4f37
--- /dev/null
+++ b/libs/exoplayer-core-2.9.0.aar
Binary files differ
diff --git a/libs/google-java-format-1.4-all-deps.jar b/libs/google-java-format-1.4-all-deps.jar
new file mode 100644
index 0000000..b10bfbd
--- /dev/null
+++ b/libs/google-java-format-1.4-all-deps.jar
Binary files differ
diff --git a/libs/google-java-format-1.7-all-deps.jar b/libs/google-java-format-1.7-all-deps.jar
deleted file mode 100644
index e2d40de..0000000
--- a/libs/google-java-format-1.7-all-deps.jar
+++ /dev/null
Binary files differ
diff --git a/libs/guava-23.3-jre.jar b/libs/guava-23.3-jre.jar
new file mode 100644
index 0000000..b13e275
--- /dev/null
+++ b/libs/guava-23.3-jre.jar
Binary files differ
diff --git a/libs/guava-23.5-jre.jar b/libs/guava-23.5-jre.jar
new file mode 100644
index 0000000..7e5f13a
--- /dev/null
+++ b/libs/guava-23.5-jre.jar
Binary files differ
diff --git a/libs/guava-23.6-android.jar b/libs/guava-23.6-android.jar
new file mode 100644
index 0000000..01180d2
--- /dev/null
+++ b/libs/guava-23.6-android.jar
Binary files differ
diff --git a/libs/javapoet-1.8.0.jar b/libs/javapoet-1.8.0.jar
new file mode 100644
index 0000000..6758b6d
--- /dev/null
+++ b/libs/javapoet-1.8.0.jar
Binary files differ
diff --git a/libs/javawriter-2.5.1.jar b/libs/javawriter-2.5.1.jar
new file mode 100644
index 0000000..4ec579e
--- /dev/null
+++ b/libs/javawriter-2.5.1.jar
Binary files differ
diff --git a/libs/m2/animal-sniffer-annotations-1.17.jar b/libs/m2/animal-sniffer-annotations-1.17.jar
deleted file mode 100644
index 6ec7a60..0000000
--- a/libs/m2/animal-sniffer-annotations-1.17.jar
+++ /dev/null
Binary files differ
diff --git a/libs/m2/auto-common-0.10.jar b/libs/m2/auto-common-0.10.jar
deleted file mode 100644
index 8cbfa72..0000000
--- a/libs/m2/auto-common-0.10.jar
+++ /dev/null
Binary files differ
diff --git a/libs/m2/auto-factory-1.0-beta6.jar b/libs/m2/auto-factory-1.0-beta6.jar
deleted file mode 100644
index e47130f..0000000
--- a/libs/m2/auto-factory-1.0-beta6.jar
+++ /dev/null
Binary files differ
diff --git a/libs/m2/auto-value-1.5.3.jar b/libs/m2/auto-value-1.5.3.jar
deleted file mode 100644
index 99eeb0b..0000000
--- a/libs/m2/auto-value-1.5.3.jar
+++ /dev/null
Binary files differ
diff --git a/libs/m2/checker-qual-2.8.1.jar b/libs/m2/checker-qual-2.8.1.jar
deleted file mode 100644
index 09269be..0000000
--- a/libs/m2/checker-qual-2.8.1.jar
+++ /dev/null
Binary files differ
diff --git a/libs/m2/dagger-2.23.jar b/libs/m2/dagger-2.23.jar
deleted file mode 100644
index 544ee3d..0000000
--- a/libs/m2/dagger-2.23.jar
+++ /dev/null
Binary files differ
diff --git a/libs/m2/dagger-android-2.23.aar b/libs/m2/dagger-android-2.23.aar
deleted file mode 100644
index 9578dcd..0000000
--- a/libs/m2/dagger-android-2.23.aar
+++ /dev/null
Binary files differ
diff --git a/libs/m2/dagger-android-jarimpl-2.23.jar b/libs/m2/dagger-android-jarimpl-2.23.jar
deleted file mode 100644
index 94a2bbe..0000000
--- a/libs/m2/dagger-android-jarimpl-2.23.jar
+++ /dev/null
Binary files differ
diff --git a/libs/m2/dagger-android-processor-2.23.jar b/libs/m2/dagger-android-processor-2.23.jar
deleted file mode 100644
index 500149c..0000000
--- a/libs/m2/dagger-android-processor-2.23.jar
+++ /dev/null
Binary files differ
diff --git a/libs/m2/dagger-compiler-2.23.jar b/libs/m2/dagger-compiler-2.23.jar
deleted file mode 100644
index b7cb162..0000000
--- a/libs/m2/dagger-compiler-2.23.jar
+++ /dev/null
Binary files differ
diff --git a/libs/m2/dagger-jarjar-rules.txt b/libs/m2/dagger-jarjar-rules.txt
deleted file mode 100644
index 618c243..0000000
--- a/libs/m2/dagger-jarjar-rules.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-# shade guava to avoid conflicts with guava embedded in Error Prone.
-rule com.google.common.** com.google.dagger.common.@1
-rule com.google.auto.** com.google.dagger.auto.@1
-
diff --git a/libs/m2/dagger-producers-2.23.jar b/libs/m2/dagger-producers-2.23.jar
deleted file mode 100644
index cb1cef9..0000000
--- a/libs/m2/dagger-producers-2.23.jar
+++ /dev/null
Binary files differ
diff --git a/libs/m2/dagger-spi-2.23.jar b/libs/m2/dagger-spi-2.23.jar
deleted file mode 100644
index 6af1494..0000000
--- a/libs/m2/dagger-spi-2.23.jar
+++ /dev/null
Binary files differ
diff --git a/libs/m2/error_prone_annotations-2.3.2.jar b/libs/m2/error_prone_annotations-2.3.2.jar
deleted file mode 100644
index bc2584d..0000000
--- a/libs/m2/error_prone_annotations-2.3.2.jar
+++ /dev/null
Binary files differ
diff --git a/libs/m2/failureaccess-1.0.1.jar b/libs/m2/failureaccess-1.0.1.jar
deleted file mode 100644
index 9b56dc7..0000000
--- a/libs/m2/failureaccess-1.0.1.jar
+++ /dev/null
Binary files differ
diff --git a/libs/m2/guava-28.0-android.jar b/libs/m2/guava-28.0-android.jar
deleted file mode 100644
index 516fc5f..0000000
--- a/libs/m2/guava-28.0-android.jar
+++ /dev/null
Binary files differ
diff --git a/libs/m2/guava-28.0-jre.jar b/libs/m2/guava-28.0-jre.jar
deleted file mode 100644
index f254aae..0000000
--- a/libs/m2/guava-28.0-jre.jar
+++ /dev/null
Binary files differ
diff --git a/libs/m2/j2objc-annotations-1.3.jar b/libs/m2/j2objc-annotations-1.3.jar
deleted file mode 100644
index a429c72..0000000
--- a/libs/m2/j2objc-annotations-1.3.jar
+++ /dev/null
Binary files differ
diff --git a/libs/m2/javac-shaded-9-dev-r4023-3.jar b/libs/m2/javac-shaded-9-dev-r4023-3.jar
deleted file mode 100644
index d7b3fd8..0000000
--- a/libs/m2/javac-shaded-9-dev-r4023-3.jar
+++ /dev/null
Binary files differ
diff --git a/libs/m2/javapoet-1.11.1.jar b/libs/m2/javapoet-1.11.1.jar
deleted file mode 100644
index 27a18e8..0000000
--- a/libs/m2/javapoet-1.11.1.jar
+++ /dev/null
Binary files differ
diff --git a/libs/m2/jsr305-3.0.2.jar b/libs/m2/jsr305-3.0.2.jar
deleted file mode 100644
index 59222d9..0000000
--- a/libs/m2/jsr305-3.0.2.jar
+++ /dev/null
Binary files differ
diff --git a/libs/m2/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar b/libs/m2/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar
deleted file mode 100644
index 45832c0..0000000
--- a/libs/m2/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar
+++ /dev/null
Binary files differ
diff --git a/libs/m2/pom-jre.xml b/libs/m2/pom-jre.xml
deleted file mode 100644
index 2d834c3..0000000
--- a/libs/m2/pom-jre.xml
+++ /dev/null
@@ -1,47 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2019 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
-  -->
-
-<!-- JRE version of libs, in particular guava -->
-<project>
-    <modelVersion>4.0.0</modelVersion>
-    <groupId>com.android.tv</groupId>
-    <artifactId>jre-libs</artifactId>
-    <version>1</version>
-
-    <repositories>
-        <repository>
-            <id>google</id>
-            <name>Google Maven Repository</name>
-            <url>https://maven.google.com</url>
-            <layout>default</layout>
-            <snapshots>
-                <enabled>false</enabled>
-            </snapshots>
-        </repository>
-    </repositories>
-
-    <dependencies>
-
-
-        <dependency>
-            <groupId>com.google.guava</groupId>
-            <artifactId>guava</artifactId>
-            <version>28.0-jre</version>
-        </dependency>
-
-    </dependencies>
-</project>
\ No newline at end of file
diff --git a/libs/m2/pom.xml b/libs/m2/pom.xml
deleted file mode 100644
index 5a232d5..0000000
--- a/libs/m2/pom.xml
+++ /dev/null
@@ -1,98 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2019 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
-  -->
-<project>
-    <modelVersion>4.0.0</modelVersion>
-    <groupId>com.android.tv</groupId>
-    <artifactId>libs</artifactId>
-    <version>1</version>
-
-    <repositories>
-        <repository>
-            <id>google</id>
-            <name>Google Maven Repository</name>
-            <url>https://maven.google.com</url>
-            <layout>default</layout>
-            <snapshots>
-                <enabled>false</enabled>
-            </snapshots>
-        </repository>
-    </repositories>
-
-    <dependencies>
-        <dependency>
-            <groupId>com.google.auto</groupId>
-            <artifactId>auto-common</artifactId>
-            <version>0.10</version>
-        </dependency>
-        <dependency>
-            <groupId>com.google.auto.factory</groupId>
-            <artifactId>auto-factory</artifactId>
-            <version>1.0-beta6</version>
-        </dependency>
-        <dependency>
-            <groupId>com.google.dagger</groupId>
-            <artifactId>dagger</artifactId>
-            <version>2.23</version>
-        </dependency>
-        <dependency>
-            <groupId>com.google.dagger</groupId>
-            <artifactId>dagger-android</artifactId>
-            <type>aar</type>
-            <version>2.23</version>
-        </dependency>
-        <dependency>
-            <groupId>com.google.dagger</groupId>
-            <artifactId>dagger-android-jarimpl</artifactId>
-            <version>2.23</version>
-        </dependency>
-        <dependency>
-            <groupId>com.google.dagger</groupId>
-            <artifactId>dagger-android-processor</artifactId>
-            <version>2.23</version>
-        </dependency>
-        <dependency>
-            <groupId>com.google.dagger</groupId>
-            <artifactId>dagger-compiler</artifactId>
-            <version>2.23</version>
-        </dependency>
-        <dependency>
-            <groupId>com.google.dagger</groupId>
-            <artifactId>dagger-producers</artifactId>
-            <version>2.23</version>
-        </dependency>
-        <dependency>
-            <groupId>com.google.dagger</groupId>
-            <artifactId>dagger-spi</artifactId>
-            <version>2.23</version>
-        </dependency>
-
-
-        <dependency>
-            <groupId>com.google.guava</groupId>
-            <artifactId>guava</artifactId>
-            <version>28.0-android</version>
-        </dependency>
-
-        <!-- The host version of guava is listed in pom-jre.xml -->
-
-        <dependency>
-            <groupId>com.squareup</groupId>
-            <artifactId>javapoet</artifactId>
-            <version>1.11.1</version>
-        </dependency>
-    </dependencies>
-</project>
\ No newline at end of file
diff --git a/libs/m2/protobuf-java-3.7.0.jar b/libs/m2/protobuf-java-3.7.0.jar
deleted file mode 100644
index eebaefe..0000000
--- a/libs/m2/protobuf-java-3.7.0.jar
+++ /dev/null
Binary files differ
diff --git a/libs/m2/update.sh b/libs/m2/update.sh
deleted file mode 100755
index ee455c7..0000000
--- a/libs/m2/update.sh
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2019 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.
-
-
-git rm *.jar *.aar
-
-EXCLUDES=google-java-format,javax.inject,support-annotations,jsr250-api,checker-compat-qual
-
-mvn \
-  -DoutputDirectory=${pwd}  \
-  dependency:copy-dependencies \
-  -DincludeScope=runtime \
-  -DexcludeArtifactIds=${EXCLUDES}
-
-mvn \
-  -DoutputDirectory=${pwd}  \
-  -f pom-jre.xml \
-  dependency:copy-dependencies \
-  -DincludeScope=runtime \
-  -DexcludeArtifactIds=${EXCLUDES}
-
-git add *.jar *.aar
-
-
diff --git a/libs/truth-0.36.jar b/libs/truth-0.36.jar
new file mode 100644
index 0000000..8174e4a
--- /dev/null
+++ b/libs/truth-0.36.jar
Binary files differ
diff --git a/libs/truth-0.45.jar b/libs/truth-0.45.jar
deleted file mode 100644
index 76e4da8..0000000
--- a/libs/truth-0.45.jar
+++ /dev/null
Binary files differ
diff --git a/partner_support/AndroidManifest.xml b/partner_support/AndroidManifest.xml
index 8f80708..45a693f 100644
--- a/partner_support/AndroidManifest.xml
+++ b/partner_support/AndroidManifest.xml
@@ -17,6 +17,6 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.google.android.tv.partner.support"
     android:versionCode="1">
-  <uses-sdk android:targetSdkVersion="28" android:minSdkVersion="23"/>
+  <uses-sdk android:targetSdkVersion="27" android:minSdkVersion="23"/>
   <application />
 </manifest>
diff --git a/partner_support/g3doc/CloudEpgForPartners.md b/partner_support/g3doc/CloudEpgForPartners.md
new file mode 100644
index 0000000..bec6b50
--- /dev/null
+++ b/partner_support/g3doc/CloudEpgForPartners.md
@@ -0,0 +1,112 @@
+# 3rd party instructions for using Cloud EPG feature of Live Channels
+
+Partners can ask Live Channels to retrieve EPG data for their TV Input Service
+using live channels
+
+## Prerequisites
+
+*   Updated agreement with Google
+*   Oreo or patched Nougat
+
+## Nougat
+
+To use cloud epg with Nougat you will need the following changes.
+
+### Patch TVProvider
+
+To run in Nougat you must cherry pick [change
+455319](https://android-review.googlesource.com/c/platform/packages/providers/TvProvider/+/455319)
+to TV Provider.
+
+### Customisation
+
+Indicate TvProvider is patched by including the following in their TV
+customization resource
+
+```
+<bool name="tvprovider_allows_system_inserts_to_program_table">true</bool>
+```
+
+See https://source.android.com/devices/tv/customize-tv-app
+
+## **Input Setup**
+
+During the input setup activity, the TIS will query the content provider for
+lineups in a given postal code. The TIS then inserts a row to the inputs table
+with input_id and lineup_id
+
+On completion of the activity the TIS sets the extra data in the result to
+
+*   `com.android.tv.extra.USE_CLOUD_EPG = true`
+*   `TvInputInfo.EXTRA_INPUT_ID` with their input_id
+
+This is used to tell Live Channels to immediately start the EPG fetch for that
+input.
+
+### Sample Input Setup code.
+
+A complete sample is at
+../third_party/samples/src/com/example/partnersupportsampletvinput
+
+#### query lineup
+
+```java
+ private AsyncTask<Void, Void, List<Lineup>> createFetchLineupsTask() {
+        return new AsyncTask<Void, Void, List<Lineup>>() {
+            @Override
+            protected List<Lineup> doInBackground(Void... params) {
+                ContentResolver cr = getActivity().getContentResolver();
+
+                List<Lineup> results = new ArrayList<>();
+                Cursor cursor =
+                        cr.query(
+                                Uri.parse(
+                                        "content://com.android.tv.data.epg/lineups/postal_code/"
+                                                + ZIP),
+                                null,
+                                null,
+                                null,
+                                null);
+
+                while (cursor.moveToNext()) {
+                    String id = cursor.getString(0);
+                    String name = cursor.getString(1);
+                    String channels = cursor.getString(2);
+                    results.add(new Lineup(id, name, channels));
+                }
+
+                return results;
+            }
+
+            @Override
+            protected void onPostExecute(List<Lineup> lineups) {
+                showLineups(lineups);
+            }
+        };
+    }
+```
+
+#### Insert cloud_epg_input
+
+```java
+ContentValues values = new ContentValues();
+values.put(EpgContract.EpgInputs.COLUMN_INPUT_ID, SampleTvInputService.INPUT_ID);
+values.put(EpgContract.EpgInputs.COLUMN_LINEUP_ID, lineup.getId());
+ContentResolver contentResolver = getActivity().getContentResolver();
+EpgInput epgInput = EpgInputs.queryEpgInput(contentResolver, SampleTvInputService.INPUT_ID);
+if (epgInput == null) {
+    contentResolver.insert(EpgContract.EpgInputs.CONTENT_URI, values);
+} else {
+    values.put(EpgContract.EpgInputs.COLUMN_ID, epgInput.getId());
+    EpgInputs.update(contentResolver, EpgInput.createEpgChannel(values));
+}
+```
+
+#### Return use_cloud_epg
+
+```java
+Intent data = new Intent();
+data.putExtra(TvInputInfo.EXTRA_INPUT_ID, inputId);
+data.putExtra(com.android.tv.extra.USE_CLOUD_EPG, true);
+setResult(Activity.RESULT_OK, data);
+```
diff --git a/partner_support/g3doc/SeriesIdColumnForPartners.md b/partner_support/g3doc/SeriesIdColumnForPartners.md
new file mode 100644
index 0000000..cd44db0
--- /dev/null
+++ b/partner_support/g3doc/SeriesIdColumnForPartners.md
@@ -0,0 +1,30 @@
+# 3rd party instructions for using series recording feature of Live Channels
+
+## Prerequisites
+
+*   Updated agreement with Google
+*   Oreo or patched Nougat
+
+## Nougat
+
+To enable series recording with Nougat you will need the following changes.
+
+### Patch TVProvider
+
+To run in Nougat you must backport the following changes
+
+*   [Filter out non-existing customized columns in
+    DB](https://partner-android.googlesource.com/platform/packages/providers/TvProvider/+/142162af889b2c124bb012eea608c6a65eed54bb)
+*   [Add TvProvider methods to get and add
+    columns](https://partner-android.googlesource.com/platform/packages/providers/TvProvider/+/cda6788ae903513a555fd3e07a5a1c14218c40a2)
+
+### Customisation
+
+Indicate TvProvider is patched by including the following in their TV
+customization resource
+
+```
+<bool name="tvprovider_allows_column_creation">true</bool>
+```
+
+See https://source.android.com/devices/tv/customize-tv-app
diff --git a/partner_support/g3doc/TurnOffEmbeddedTuner.md b/partner_support/g3doc/TurnOffEmbeddedTuner.md
new file mode 100644
index 0000000..0ba7cff
--- /dev/null
+++ b/partner_support/g3doc/TurnOffEmbeddedTuner.md
@@ -0,0 +1,15 @@
+# 3rd party instructions turning off the embedded tuner in Live Channels
+
+Partners that have a built in tuner should provide a TV Input like
+SampleDvbTuner. When partners provide their own tuner they MUST turn of the
+embedded tuner in Live Channels.
+
+### Customisation
+
+Indicate Live Channels should not use it's embedded tuner implementation.
+
+```
+<bool name="turn_off_embedded_tuner">true</bool>
+```
+
+See https://source.android.com/devices/tv/customize-tv-app
diff --git a/partner_support/sample_customization/AndroidManifest.xml b/partner_support/sample_customization/AndroidManifest.xml
index 5e4c2c7..804691a 100644
--- a/partner_support/sample_customization/AndroidManifest.xml
+++ b/partner_support/sample_customization/AndroidManifest.xml
@@ -24,7 +24,7 @@
     <uses-feature android:name="android.software.leanback" android:required="true" />
     <uses-feature android:name="android.hardware.touchscreen" android:required="false" />
 
-    <uses-sdk android:targetSdkVersion="28" android:minSdkVersion="23"/>
+    <uses-sdk android:targetSdkVersion="27" android:minSdkVersion="23"/>
 
     <application android:label="Partner Customization"
             android:theme="@android:style/Theme.Holo.Light.NoActionBar"
diff --git a/partner_support/samples/Android.bp b/partner_support/samples/Android.bp
deleted file mode 100644
index 9c1d2db..0000000
--- a/partner_support/samples/Android.bp
+++ /dev/null
@@ -1,25 +0,0 @@
-android_app {
-    name: "PartnerSupportSampleTvInput",
-
-    // Include all java files.
-    srcs: ["src/**/*.java"],
-
-    static_libs: [
-        "androidx.leanback_leanback",
-        "androidx.tvprovider_tvprovider",
-        "live-channels-partner-support",
-    ],
-
-    optimize: {
-        enabled: false,
-    },
-    // Overlay view related functionality requires system APIs.
-    sdk_version: "system_current",
-    min_sdk_version: "23", // M
-
-    // Required for com.android.tv.permission.RECEIVE_INPUT_EVENT
-    privileged: true,
-
-    resource_dirs: ["res"],
-
-}
diff --git a/partner_support/samples/Android.mk b/partner_support/samples/Android.mk
new file mode 100644
index 0000000..2e771a5
--- /dev/null
+++ b/partner_support/samples/Android.mk
@@ -0,0 +1,33 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# Include all java files.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := PartnerSupportSampleTvInput
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android-support-annotations \
+    live-channels-partner-support
+
+LOCAL_STATIC_ANDROID_LIBRARIES := \
+    android-support-compat \
+    android-support-core-ui \
+    android-support-v7-recyclerview \
+    android-support-v17-leanback \
+    androidx.tvprovider_tvprovider
+
+LOCAL_USE_AAPT2 := true
+
+LOCAL_PROGUARD_ENABLED := disabled
+# Overlay view related functionality requires system APIs.
+LOCAL_SDK_VERSION := system_current
+LOCAL_MIN_SDK_VERSION := 23  # M
+
+# Required for com.android.tv.permission.RECEIVE_INPUT_EVENT
+LOCAL_PRIVILEGED_MODULE := true
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
+include $(BUILD_PACKAGE)
diff --git a/partner_support/samples/AndroidManifest.xml b/partner_support/samples/AndroidManifest.xml
index 65b2a3b..d91c603 100644
--- a/partner_support/samples/AndroidManifest.xml
+++ b/partner_support/samples/AndroidManifest.xml
@@ -29,7 +29,7 @@
     <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.tv.permission.RECEIVE_INPUT_EVENT" />
-    <uses-sdk android:targetSdkVersion="28" android:minSdkVersion="23"/>
+    <uses-sdk android:targetSdkVersion="27" android:minSdkVersion="23"/>
     <!--TODO(b/68949299): remove tool hint when we have smaller dependency targets-->
     <application android:label="@string/partner_support_sample_tv_input"
             tools:replace="android:label,icon,theme,appComponentFactory"
diff --git a/partner_support/samples/src/com/example/partnersupportsampletvinput/ChannelScanFragment.java b/partner_support/samples/src/com/example/partnersupportsampletvinput/ChannelScanFragment.java
index d449bb5..ec7589c 100644
--- a/partner_support/samples/src/com/example/partnersupportsampletvinput/ChannelScanFragment.java
+++ b/partner_support/samples/src/com/example/partnersupportsampletvinput/ChannelScanFragment.java
@@ -23,10 +23,10 @@
 import android.os.Bundle;
 import android.os.SystemClock;
 import android.support.annotation.NonNull;
-import androidx.leanback.app.GuidedStepFragment;
-import androidx.leanback.widget.GuidanceStylist;
-import androidx.leanback.widget.GuidanceStylist.Guidance;
-import androidx.leanback.widget.GuidedAction;
+import android.support.v17.leanback.app.GuidedStepFragment;
+import android.support.v17.leanback.widget.GuidanceStylist;
+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;
diff --git a/partner_support/samples/src/com/example/partnersupportsampletvinput/LineupSelectionFragment.java b/partner_support/samples/src/com/example/partnersupportsampletvinput/LineupSelectionFragment.java
index 7486a98..8c3ca77 100644
--- a/partner_support/samples/src/com/example/partnersupportsampletvinput/LineupSelectionFragment.java
+++ b/partner_support/samples/src/com/example/partnersupportsampletvinput/LineupSelectionFragment.java
@@ -24,24 +24,21 @@
 import android.os.Bundle;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
+import android.support.v17.leanback.app.GuidedStepFragment;
+import android.support.v17.leanback.widget.GuidanceStylist;
+import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
+import android.support.v17.leanback.widget.GuidedAction;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Pair;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-
-import androidx.leanback.app.GuidedStepFragment;
-import androidx.leanback.widget.GuidanceStylist;
-import androidx.leanback.widget.GuidanceStylist.Guidance;
-import androidx.leanback.widget.GuidedAction;
-
 import com.google.android.tv.partner.support.EpgContract;
 import com.google.android.tv.partner.support.EpgInput;
 import com.google.android.tv.partner.support.EpgInputs;
 import com.google.android.tv.partner.support.Lineup;
 import com.google.android.tv.partner.support.Lineups;
-
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -179,7 +176,7 @@
             List<Lineup> lineups, List<String> localChannels) {
         List<Pair<Lineup, Integer>> result = new ArrayList<>();
         for (Lineup lineup : lineups) {
-            result.add(Pair.create(lineup, getMatchCount(lineup.getChannels(), localChannels)));
+            result.add(new Pair<>(lineup, getMatchCount(lineup.getChannels(), localChannels)));
         }
         // sort in decreasing order
         Collections.sort(
diff --git a/partner_support/samples/src/com/example/partnersupportsampletvinput/LocationFragment.java b/partner_support/samples/src/com/example/partnersupportsampletvinput/LocationFragment.java
index 532ff9b..9492e7e 100644
--- a/partner_support/samples/src/com/example/partnersupportsampletvinput/LocationFragment.java
+++ b/partner_support/samples/src/com/example/partnersupportsampletvinput/LocationFragment.java
@@ -19,10 +19,10 @@
 import android.app.FragmentManager;
 import android.os.Bundle;
 import android.support.annotation.NonNull;
-import androidx.leanback.app.GuidedStepFragment;
-import androidx.leanback.widget.GuidanceStylist;
-import androidx.leanback.widget.GuidanceStylist.Guidance;
-import androidx.leanback.widget.GuidedAction;
+import android.support.v17.leanback.app.GuidedStepFragment;
+import android.support.v17.leanback.widget.GuidanceStylist;
+import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
+import android.support.v17.leanback.widget.GuidedAction;
 import java.util.List;
 
 /** Location Fragment for users to enter postal code */
diff --git a/partner_support/samples/src/com/example/partnersupportsampletvinput/ResultFragment.java b/partner_support/samples/src/com/example/partnersupportsampletvinput/ResultFragment.java
index 0c89318..a1c17ac 100644
--- a/partner_support/samples/src/com/example/partnersupportsampletvinput/ResultFragment.java
+++ b/partner_support/samples/src/com/example/partnersupportsampletvinput/ResultFragment.java
@@ -21,10 +21,10 @@
 import android.media.tv.TvInputInfo;
 import android.os.Bundle;
 import android.support.annotation.NonNull;
-import androidx.leanback.app.GuidedStepFragment;
-import androidx.leanback.widget.GuidanceStylist;
-import androidx.leanback.widget.GuidanceStylist.Guidance;
-import androidx.leanback.widget.GuidedAction;
+import android.support.v17.leanback.app.GuidedStepFragment;
+import android.support.v17.leanback.widget.GuidanceStylist;
+import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
+import android.support.v17.leanback.widget.GuidedAction;
 import com.google.android.tv.partner.support.EpgContract;
 import java.util.List;
 
diff --git a/partner_support/samples/src/com/example/partnersupportsampletvinput/SampleTvInputSetupActivity.java b/partner_support/samples/src/com/example/partnersupportsampletvinput/SampleTvInputSetupActivity.java
index e11ebdf..a0a7588 100644
--- a/partner_support/samples/src/com/example/partnersupportsampletvinput/SampleTvInputSetupActivity.java
+++ b/partner_support/samples/src/com/example/partnersupportsampletvinput/SampleTvInputSetupActivity.java
@@ -18,7 +18,7 @@
 
 import android.app.Activity;
 import android.os.Bundle;
-import androidx.leanback.app.GuidedStepFragment;
+import android.support.v17.leanback.app.GuidedStepFragment;
 
 /** The setup activity for partner support sample TV input. */
 public class SampleTvInputSetupActivity extends Activity {
diff --git a/partner_support/samples/src/com/example/partnersupportsampletvinput/WelcomeFragment.java b/partner_support/samples/src/com/example/partnersupportsampletvinput/WelcomeFragment.java
index 96632d3..286f34f 100644
--- a/partner_support/samples/src/com/example/partnersupportsampletvinput/WelcomeFragment.java
+++ b/partner_support/samples/src/com/example/partnersupportsampletvinput/WelcomeFragment.java
@@ -19,10 +19,10 @@
 import android.app.FragmentManager;
 import android.os.Bundle;
 import android.support.annotation.NonNull;
-import androidx.leanback.app.GuidedStepFragment;
-import androidx.leanback.widget.GuidanceStylist;
-import androidx.leanback.widget.GuidanceStylist.Guidance;
-import androidx.leanback.widget.GuidedAction;
+import android.support.v17.leanback.app.GuidedStepFragment;
+import android.support.v17.leanback.widget.GuidanceStylist;
+import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
+import android.support.v17.leanback.widget.GuidedAction;
 import java.util.List;
 
 /** Welcome Fragment shows welcome information for users */
diff --git a/partner_support/src/com/google/android/tv/partner/support/EpgInput.java b/partner_support/src/com/google/android/tv/partner/support/EpgInput.java
index c591c9f..20b3542 100644
--- a/partner_support/src/com/google/android/tv/partner/support/EpgInput.java
+++ b/partner_support/src/com/google/android/tv/partner/support/EpgInput.java
@@ -20,7 +20,7 @@
 import com.google.auto.value.AutoValue;
 
 /**
- * Value class representing a TV Input that uses TV app EPG.
+ * Value class representing a TV Input that uses Live TV EPG.
  *
  * @see {@link EpgContract.EpgInputs}
  */
diff --git a/partner_support/src/com/google/android/tv/partner/support/TunerSetupUtils.java b/partner_support/src/com/google/android/tv/partner/support/TunerSetupUtils.java
index d50db7d..e25d583 100644
--- a/partner_support/src/com/google/android/tv/partner/support/TunerSetupUtils.java
+++ b/partner_support/src/com/google/android/tv/partner/support/TunerSetupUtils.java
@@ -20,7 +20,6 @@
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Pair;
-
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -40,7 +39,7 @@
         List<List<String>> parsedLocalChannels = parseChannelNumbers(localChannels);
         for (Lineup lineup : lineups) {
             result.add(
-                    Pair.create(lineup, getMatchCount(lineup.getChannels(), parsedLocalChannels)));
+                    new Pair<>(lineup, getMatchCount(lineup.getChannels(), parsedLocalChannels)));
         }
         // sort in decreasing order
         Collections.sort(
diff --git a/partner_support/tests/robotests/javatests/com/google/android/tv/partner/support/BaseCustomizationTest.java b/partner_support/tests/robotests/javatests/com/google/android/tv/partner/support/BaseCustomizationTest.java
index 03d68e4..e217058 100644
--- a/partner_support/tests/robotests/javatests/com/google/android/tv/partner/support/BaseCustomizationTest.java
+++ b/partner_support/tests/robotests/javatests/com/google/android/tv/partner/support/BaseCustomizationTest.java
@@ -17,17 +17,16 @@
 package com.google.android.tv.partner.support;
 
 import static com.google.common.truth.Truth.assertThat;
-
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
-
 import com.android.tv.testing.TestSingletonApp;
 import com.android.tv.testing.constants.ConfigConstants;
-
+import java.util.ArrayList;
+import java.util.List;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -35,9 +34,6 @@
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 
-import java.util.ArrayList;
-import java.util.List;
-
 /** Tests for {@link BaseCustomization}. */
 
 // TODO: move to partner-support
diff --git a/partner_support/tests/robotests/javatests/com/google/android/tv/partner/support/TunerSetupUtilsTest.java b/partner_support/tests/robotests/javatests/com/google/android/tv/partner/support/TunerSetupUtilsTest.java
index 8d089e5..d9b48cf 100644
--- a/partner_support/tests/robotests/javatests/com/google/android/tv/partner/support/TunerSetupUtilsTest.java
+++ b/partner_support/tests/robotests/javatests/com/google/android/tv/partner/support/TunerSetupUtilsTest.java
@@ -19,18 +19,16 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import com.android.tv.testing.constants.ConfigConstants;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
+import com.google.thirdparty.robolectric.GoogleRobolectricTestRunner;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
 
 /** Tests for {@link TunerSetupUtils} */
-@RunWith(RobolectricTestRunner.class)
+@RunWith(GoogleRobolectricTestRunner.class)
 @Config(sdk = ConfigConstants.SDK)
 public class TunerSetupUtilsTest {
 
diff --git a/res/layout/details_overview.xml b/res/layout/details_overview.xml
index 541f3fb..dbcf205 100644
--- a/res/layout/details_overview.xml
+++ b/res/layout/details_overview.xml
@@ -55,7 +55,7 @@
                 android:orientation="vertical" >
 
                 <!-- layout_marginStart and layout_marginEnd are overridden -->
-                <androidx.leanback.widget.NonOverlappingFrameLayout
+                <android.support.v17.leanback.widget.NonOverlappingFrameLayout
                     android:id="@+id/details_overview_description"
                     android:layout_width="match_parent"
                     android:layout_height="0dp"
@@ -69,7 +69,7 @@
 
                 <!-- horizontalSpacing is defined as @dimen/lb_details_overview_action_items_spacing
                      in newer versions of Leanback Library than LC uses. -->
-                <androidx.leanback.widget.HorizontalGridView
+                <android.support.v17.leanback.widget.HorizontalGridView
                     android:id="@+id/details_overview_actions"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
diff --git a/res/layout/dvr_details_description.xml b/res/layout/dvr_details_description.xml
index e37d8b0..ee74952 100644
--- a/res/layout/dvr_details_description.xml
+++ b/res/layout/dvr_details_description.xml
@@ -21,7 +21,7 @@
     android:layout_height="wrap_content">
 
     <!-- Top margins are set programatically -->
-    <androidx.leanback.widget.ResizingTextView
+    <android.support.v17.leanback.widget.ResizingTextView
         android:id="@+id/dvr_details_description_title"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
diff --git a/res/layout/item_list.xml b/res/layout/item_list.xml
index 233aa41..c06b29a 100644
--- a/res/layout/item_list.xml
+++ b/res/layout/item_list.xml
@@ -33,7 +33,7 @@
          and compensate the same space with padding.
 
          The accurate layout height is set in MenuRowView.onBind(). -->
-    <androidx.leanback.widget.HorizontalGridView
+    <android.support.v17.leanback.widget.HorizontalGridView
         android:id="@+id/list_view"
         style="@style/menu_row_contents_view"
         android:clipChildren="false"
diff --git a/res/layout/option_fragment.xml b/res/layout/option_fragment.xml
index 50bf991..4a4cbbd 100644
--- a/res/layout/option_fragment.xml
+++ b/res/layout/option_fragment.xml
@@ -34,7 +34,7 @@
         android:textColor="@color/option_item_text_color"
         android:singleLine="true" />
 
-    <androidx.leanback.widget.VerticalGridView
+    <android.support.v17.leanback.widget.VerticalGridView
         android:id="@+id/side_panel_list"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
diff --git a/res/layout/pin_dialog.xml b/res/layout/pin_dialog.xml
index 84807f2..d40d70e 100644
--- a/res/layout/pin_dialog.xml
+++ b/res/layout/pin_dialog.xml
@@ -55,8 +55,8 @@
             android:fontFamily="@string/font"
             android:singleLine="false" />
 
-        <com.android.tv.dialog.picker.TvPinPicker
-            android:id="@+id/tv_pin_picker"
+        <com.android.tv.dialog.picker.PinPicker
+            android:id="@+id/pin_picker"
             android:importantForAccessibility="yes"
             android:layout_width="match_parent"
             android:layout_height="154dp"
diff --git a/res/layout/priority_settings_action_item.xml b/res/layout/priority_settings_action_item.xml
index fc882d9..0f51731 100644
--- a/res/layout/priority_settings_action_item.xml
+++ b/res/layout/priority_settings_action_item.xml
@@ -15,13 +15,13 @@
      limitations under the License.
 -->
 
-<androidx.leanback.widget.GuidedActionItemContainer
+<android.support.v17.leanback.widget.GuidedActionItemContainer
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
     style="?attr/guidedActionItemContainerStyle"
     android:foreground="@null"
     android:outlineProvider="background">
-    <androidx.leanback.widget.CheckableImageView
+    <android.support.v17.leanback.widget.CheckableImageView
         android:id="@+id/guidedactions_item_checkmark"
         style="?attr/guidedActionItemCheckmarkStyle"
         tools:ignore="ContentDescription" />
@@ -30,16 +30,16 @@
         style="?attr/guidedActionItemIconStyle"
         tools:ignore="ContentDescription" />
 
-    <androidx.leanback.widget.NonOverlappingLinearLayout
+    <android.support.v17.leanback.widget.NonOverlappingLinearLayout
         android:id="@+id/guidedactions_item_content"
         style="?attr/guidedActionItemContentStyle" >
-        <androidx.leanback.widget.GuidedActionEditText
+        <android.support.v17.leanback.widget.GuidedActionEditText
             android:id="@+id/guidedactions_item_title"
             style="?attr/guidedActionItemTitleStyle" />
-        <androidx.leanback.widget.GuidedActionEditText
+        <android.support.v17.leanback.widget.GuidedActionEditText
             android:id="@+id/guidedactions_item_description"
             style="?attr/guidedActionItemDescriptionStyle" />
-    </androidx.leanback.widget.NonOverlappingLinearLayout>
+    </android.support.v17.leanback.widget.NonOverlappingLinearLayout>
 
     <ImageView
         android:id="@+id/guidedactions_item_chevron"
@@ -53,4 +53,4 @@
         android:adjustViewBounds="true"
         android:src="@drawable/ic_draggable_white"
         tools:ignore="ContentDescription" />
-</androidx.leanback.widget.GuidedActionItemContainer>
\ No newline at end of file
+</android.support.v17.leanback.widget.GuidedActionItemContainer>
\ No newline at end of file
diff --git a/res/layout/program_guide_side_panel.xml b/res/layout/program_guide_side_panel.xml
index 9c04feb..466b7fa 100644
--- a/res/layout/program_guide_side_panel.xml
+++ b/res/layout/program_guide_side_panel.xml
@@ -32,7 +32,7 @@
     android:elevation="@dimen/program_guide_side_panel_elevation"
     android:background="@color/program_guide_side_panel_background">
 
-    <androidx.leanback.widget.SearchOrbView
+    <android.support.v17.leanback.widget.SearchOrbView
         android:id="@+id/program_guide_side_panel_search_orb"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
@@ -41,7 +41,7 @@
         android:nextFocusDown="@+id/program_guide_side_panel_grid_view"
         android:visibility="gone" />
 
-    <androidx.leanback.widget.VerticalGridView
+    <android.support.v17.leanback.widget.VerticalGridView
         android:id="@id/program_guide_side_panel_grid_view"
         android:layout_width="@dimen/program_guide_side_panel_item_width"
         android:layout_height="match_parent"
diff --git a/res/values/arrays-custom.xml b/res/values/arrays-custom.xml
deleted file mode 100644
index 252d6f4..0000000
--- a/res/values/arrays-custom.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2019 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.
-  -->
-
-<!-- These are resources that are expected to be different for OEM apps -->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <!-- Keep the title and description arrays in sync -->
-
-    <!-- Titles in the onboarding page.  [CHAR LIMIT=100]-->
-    <string-array name="welcome_page_titles">
-        <item><xliff:g id="app_name">Live TV</xliff:g> </item>
-        <item>A simple way to discover content</item>
-        <item>Download apps, get more channels</item>
-        <item>Customize your channel line-up</item>
-    </string-array>
-
-
-    <!-- Descriptions in the onboarding page. [CHAR LIMIT=NONE] -->
-    <string-array name="welcome_page_descriptions">
-        <item>Watch content from your apps like watching channels on TV.</item>
-        <item>Browse content from your apps with a familiar guide and friendly interface,
-\njust like channels on TV.</item>
-        <item>Add more channels by installing apps that offer live channels.
-\nFind compatible apps in Google Play Store by using the link within the TV menu.</item>
-        <!-- Refer to @string/settings_channel_source_item_setup for "Channel sources" menu
-             and @string/options_item_settings for "Settings" menu. -->
-        <item>Set up your newly installed channel sources to customize your channel list.
-\nChoose the Channel sources within the Settings menu to get started.</item>
-    </string-array>
-</resources>
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 9ef028a..0604dd2 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -150,4 +150,24 @@
         <item>Tech/Science</item>
     </string-array>
 
+    <!-- Titles in the onboarding page. -->
+    <string-array name="welcome_page_titles">
+        <item><xliff:g id="app_name">Live TV</xliff:g> </item>
+        <item>A simple way to discover content</item>
+        <item>Download apps, get more channels</item>
+        <item>Customize your channel line-up</item>
+    </string-array>
+
+    <!-- Descriptions in the onboarding page. -->
+    <string-array name="welcome_page_descriptions">
+        <item>Watch content from your apps like watching channels on TV.</item>
+        <item>Browse content from your apps with a familiar guide and friendly interface,
+\njust like channels on TV.</item>
+        <item>Add more channels by installing apps that offer live channels.
+\nFind compatible apps in the online store by using the link within the TV menu.</item>
+        <!-- Refer to @string/settings_channel_source_item_setup for "Channel sources" menu
+             and @string/options_item_settings for "Settings" menu. -->
+        <item>Set up your newly installed channel sources to customize your channel list.
+\nChoose the Channel sources within the Settings menu to get started.</item>
+    </string-array>
 </resources>
diff --git a/res/values/rating_system_strings.xml b/res/values/rating_system_strings.xml
index 9922cb1..45c48d8 100644
--- a/res/values/rating_system_strings.xml
+++ b/res/values/rating_system_strings.xml
@@ -16,10 +16,9 @@
   -->
 
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Age based TV content rating strings used in DVB, ISDB and DTMB.
-         For more info, please see STD-B10 in http://www.dibeg.org/techp/aribstd/aribstd.html (ISDB),
-         Table 81 of DVB SI (EN 300 468 V1.14.1) in https://www.dvb.org/standards (DVB)
-         and http://www.gb688.cn/bzgk/gb/newGbInfo?hcno=59E83CA701AEB4248E115BC043688FEC (DTMB).-->
+    <!-- Age based TV content rating strings used in DVB and ISDB.
+         For more info, please see STD-B10 in http://www.dibeg.org/techp/aribstd/aribstd.html (ISDB)
+         and Table 81 of DVB SI (EN 300 468 V1.14.1) in https://www.dvb.org/standards (DVB).-->
     <string name="description_age_4">Recommended for ages 4 and over.</string>
     <string name="description_age_5">Recommended for ages 5 and over.</string>
     <string name="description_age_6">Recommended for ages 6 and over.</string>
@@ -110,7 +109,6 @@
     <!-- A TV content rating of DVB for adult [CHAR LIMIT=NONE] -->
     <string name="description_es_dvb_x">Recommended for adults.</string>
 
-
     <!-- TV content rating system strings for KR TV. These strings are from
          http://www.law.go.kr/admRulLsInfoP.do?admRulSeq=2000000118507 but they are translated
          from Korean to English. -->
@@ -161,19 +159,4 @@
     <string name="description_us_mv_pg13">Parents strongly cautioned. Some material may be inappropriate for pre-teenagers.</string>
     <string name="description_us_mv_r">Restricted, Contains some adult material. Parents are urged to learn more about the film before taking their young children with them.</string>
     <string name="description_us_mv_nc17">No one 17 and under admitted. Clearly adult. Children are not admitted.</string>
-
-    <!-- TV content rating system strings for NZ TV. These strings are from
-         https://bsa.govt.nz/images/03_BSA_FREE-TO-AIR-TV_CLASSIFICATIONS_DRAFT.pdf -->
-    <string name="description_nz_fta_tv_g" translatable="false">Programmes which exclude material likely to be unsuitable for children. Programmes may not necessarily be designed for child viewers but should not contain material likely to alarm or distress them.</string>
-    <string name="description_nz_fta_tv_pgr" translatable="false">Programmes containing material more suited for mature audiences but not necessarily unsuitable for child viewers when subject to the guidance of a parent or an adult.</string>
-    <string name="description_nz_fta_tv_ao" translatable="false">Programmes containing adult themes and directed primarily at mature audiences.</string>
-
-    <!-- TV content rating system strings for TH TV. These strings are from
-         https://broadcast.nbtc.go.th/home/ -->
-    <string name="description_th_tv_4" translatable="false">Suitable for audiences 3 to 5 years of age.</string>
-    <string name="description_th_tv_6" translatable="false">Suitable for audiences 6 to 12 years of age.</string>
-    <string name="description_th_tv_10" translatable="false">Suitable for all audiences.</string>
-    <string name="description_th_tv_13" translatable="false">Parental guidance suggested for viewers age below 13.</string>
-    <string name="description_th_tv_18" translatable="false">Parental guidance suggested for viewers age below 18.</string>
-    <string name="description_th_tv_19" translatable="false">Not suitable for children and teenagers.</string>
 </resources>
diff --git a/res/values/strings-custom.xml b/res/values/strings-custom.xml
index 5ecb859..22f7331 100644
--- a/res/values/strings-custom.xml
+++ b/res/values/strings-custom.xml
@@ -14,18 +14,9 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-
-
-<!-- These are resources that are expected to be different for OEM apps -->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+<resources>
 
     <!-- Name of application [CHAR LIMIT=NONE] -->
     <string name="app_name" translatable="false">Live TV</string>
-    <!-- Description for channel sources screen in onboarding. [CHAR LIMIT=NONE] -->
-    <string name="setup_sources_description2"
-        meaning="Live TV version of setup_sources_description2"
-        ><xliff:g id="app_name">Live TV</xliff:g> combines the experience of traditional TV channels with streaming channels provided by apps.
-\n\nGet started by setting up the channel sources already installed. Or browse Google Play Store for more apps that offer live channels.</string>
 
-</resources>
+</resources>
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 06694a9..3682475 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -28,16 +28,16 @@
 
     <!-- Title of an application permission, listed so the user can choose
         whether they want to allow the application to do this. -->
-    <string name="permlab_receiveInputEvent" translatable="false">receive input events from <xliff:g id="app_name">Live TV</xliff:g> app</string>
+    <string name="permlab_receiveInputEvent" translatable="false">receive input events from <xliff:g id="app_name">Live TV</xliff:g>  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_receiveInputEvent" translatable="false">Allows the app to receive input events from <xliff:g id="app_name">Live TV</xliff:g> app</string>
+    <string name="permdesc_receiveInputEvent" translatable="false">Allows the app to receive input events from <xliff:g id="app_name">Live TV</xliff:g>  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 <xliff:g id="app_name">Live TV</xliff:g> app</string>
+    <string name="permlab_customizeTvApp" translatable="false">customize <xliff:g id="app_name">Live TV</xliff:g>  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 <xliff:g id="app_name">Live TV</xliff:g> app</string>
+    <string name="permdesc_customizeTvApp" translatable="false">Allows the app to customize <xliff:g id="app_name">Live TV</xliff:g>  app</string>
 
     <!-- Program information, mainly used for channel banner and program guide. -->
     <eat-comment />
@@ -388,13 +388,13 @@
     <!-- 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 TV app.</string>
+    <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 TV app.</string>
+    <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 TV app.</string>
+    <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 TV app.</string>
+    <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>
@@ -479,7 +479,7 @@
          the source video through to the display and don't provide ability to tune to a specific
          channel unless the user directly controls the external source device (e.g. game console,
          DVD player, settop box, etc) that is connected to the TV. [CHAR LIMIT=NONE] -->
-    <string name="msg_not_passthrough_input">Tuner type not suitable. Please launch <xliff:g id="app_name">Live TV</xliff:g> app for tuner type TV input.</string>
+    <string name="msg_not_passthrough_input">Tuner type not suitable. Please launch <xliff:g id="app_name">Live TV</xliff:g>  app for tuner type TV input.</string>
     <!-- Error message when tune is failed. [CHAR LIMIT=NONE] -->
     <string name="msg_tune_failed">Tune failed</string>
     <!-- Error message when the user attempts an action (select TIS setup-activity, app-link,
@@ -496,7 +496,7 @@
          (commands for external device)  [CHAR LIMIT=NONE] -->
     <string name="msg_back_key_guide">BACK key is for connected device. Press HOME button to exit.</string>
     <!-- Error message when a user denied to grant READ_TV_LISTING permission. [CHAR LIMIT=NONE] -->
-    <string name="msg_read_tv_listing_permission_denied"><xliff:g id="app_name">Live TV</xliff:g> needs permission to read the TV listings.</string>
+    <string name="msg_read_tv_listing_permission_denied"><xliff:g id="app_name">Live TV</xliff:g>  needs permission to read the TV listings.</string>
 
     <!-- Strings for debug or not to be shown to users -->
     <eat-comment />
@@ -518,17 +518,17 @@
     <!-- 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. [CHAR LIMIT=50] -->
+    <!-- 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. [CHAR LIMIT=50] -->
-    <string name="dvr_notification_channel_name" ><xliff:g id="app_name">Live TV</xliff:g> DVR</string>
-    <!-- Content title of DVR recording service's notification. [CHAR LIMIT=50] -->
-    <string name="dvr_notification_content_title" ><xliff:g id="app_name">Live TV</xliff:g> DVR</string>
-    <!-- Content text of DVR recording service's notification during recording. [CHAR LIMIT=NONE] -->
-    <string name="dvr_notification_content_text_recording" ><xliff:g id="app_name">Live TV</xliff:g> are recording.</string>
-    <!-- Content text of DVR recording service's notification during updating schedules. [CHAR LIMIT=NONE] -->
-    <string name="dvr_notification_content_text_loading" ><xliff:g id="app_name">Live TV</xliff:g> are updating recording schedules.</string>
+    <!-- Display name of DVR recording service's notification channel. -->
+    <string name="dvr_notification_channel_name" translatable="false"><xliff:g id="app_name">Live TV</xliff:g>  DVR</string>
+    <!-- Content title of DVR recording service's notification. -->
+    <string name="dvr_notification_content_title" translatable="false"><xliff:g id="app_name">Live TV</xliff:g>  DVR</string>
+    <!-- Content text of DVR recording service's notification during recording. -->
+    <string name="dvr_notification_content_text_recording" translatable="false"><xliff:g id="app_name">Live TV</xliff:g>  are recording.</string>
+    <!-- Content text of DVR recording service's notification during updating schedules. -->
+    <string name="dvr_notification_content_text_loading" translatable="false"><xliff:g id="app_name">Live TV</xliff:g>  are updating recording schedules.</string>
 
     <!-- Default content title of tuner installing notifications. -->
     <string name="tuner_install_notification_content_title" translatable="false">Install <xliff:g id="tuner_package" example="Tuner package">%s</xliff:g></string>
@@ -546,6 +546,9 @@
     <eat-comment />
     <!-- Text for the channel sources screen in onboarding. -->
     <string name="setup_sources_text">Set up your sources</string>
+    <!-- Description for channel sources screen in onboarding. -->
+    <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 the online store for more apps that offer live channels.</string>
 
     <!-- Menu item label to start DVR manager UI. -->
     <string name="channels_item_dvr">Recordings &amp; schedules</string>
@@ -690,8 +693,8 @@
         <item quantity="one">%1$d of %2$d episode is deleted</item>
         <item quantity="other">%1$d of %2$d episodes are deleted</item>
     </plurals>
-    <!-- Title of screen with settings for the recording of a TV Program or Series. [CHAR LIMIT=50] -->
-    <string name="dvr_series_settings_title">Recording settings</string>
+    <!-- Title of DVR series settings -->
+    <string name="dvr_series_settings_title" translatable="false">Recording settings</string>
     <!-- Item label to change priority of TV series for DVR -->
     <string name="dvr_series_settings_priority">Priority</string>
     <!-- Item description when the current series has the height proirty among scheduled
@@ -719,13 +722,10 @@
 
     <!-- DVR epg strings -->
     <eat-comment />
-    <!--  Button text that deletes scheduled future recordings of a TV Program or Series. [CHAR LIMIT=50] -->
-    <string name="dvr_action_delete_schedule">Delete schedule</string>
-    <!--  Button text that records the selected program. [CHAR LIMIT=50] -->
-    <string name="dvr_action_record_program">Record program</string>
-    <!-- Button text that invokes android internal storage settings activity.
-         [CHAR LIMIT=50] -->
-    <string name="dvr_action_error_storage_settings">Open storage settings</string>
+    <string name="dvr_action_delete_schedule" translatable="false">Delete schedule</string>
+    <string name="dvr_action_record_program" translatable="false">Record program</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] -->
@@ -767,10 +767,8 @@
     <!-- Dvr label in epg to indicate the recording of the program has been failed. [CHAR LIMIT=30] -->
     <string name="dvr_epg_program_recording_failed">Recording failed</string>
     <string name="dvr_epg_program_icon_text" translatable="false">DVR</string>
-    <!-- Title of a dialog box displayed when a previously scheduled recording requires an action.[CHAR LIMIT=50] -->
-    <string name="dvr_epg_channel_watch_conflict_dialog_title">Upcoming schedules</string>
-    <!-- Description in a dialog box displayed when a previously scheduled recording requires an action. [CHAR LIMIT=NONE] -->
-    <string name="dvr_epg_channel_watch_conflict_dialog_description">The program will not be recorded if you keep watching this channel. Cancel the recording, or the current channel will be blocked when the recording starts.</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. -->
     <string name="dvr_series_progress_message_reading_programs">Reading programs</string>
     <!-- Dialog action which let user view the recent recordings. -->
@@ -800,10 +798,10 @@
     <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. [CHAR LIMIT=NONE]  -->
-    <string name="dvr_error_missing_storage_description">Some of the storage used for recording is missing. Please connect the external drive you used before to re-enable recording. Alternately, you can forget the storage in the storage settings, if it\'s no longer available.</string>
-    <!-- A toast message displad to the user when the recording being requested to play is not found in storage. [CHAR LIMIT=NONE] -->
-    <string name="dvr_toast_recording_deleted">Recording not found.</string>
+    <!-- Dialog description which will be shown when the current DVR storage is not accessible. -->
+    <string name="dvr_error_missing_storage_description" translatable="false">Some of the storage used for recording is missing. Please connect the external drive you used before to re-enable recording. 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>
 
     <!-- DVR half sized dialogs -->
     <eat-comment />
@@ -910,8 +908,7 @@
 
     <!-- DVR channel banner strings -->
     <eat-comment />
-    <!-- Text desplayed on screen to show that the current program is being recorded until the time listed. [CHAR LIMIT=30] -->
-    <string name="dvr_recording_till_format">Recording till <xliff:g id="recordingEndTime" example="9:00pm">%1$s</xliff:g></string>
+    <string name="dvr_recording_till_format" translatable="false">Recording till <xliff:g id="recordingEndTime" example="9:00pm">%1$s</xliff:g></string>
 
     <!-- DVR schedule list strings -->
     <eat-comment/>
diff --git a/res/xml/tv_content_rating_systems.xml b/res/xml/tv_content_rating_systems.xml
index 361393f..aad9d61 100644
--- a/res/xml/tv_content_rating_systems.xml
+++ b/res/xml/tv_content_rating_systems.xml
@@ -286,170 +286,6 @@
         </rating-order>
     </rating-system-definition>
 
-    <!-- TV content rating system for DTMB. See http://www.gb688.cn/bzgk/gb/newGbInfo?hcno=59E83CA701AEB4248E115BC043688FEC -->
-    <rating-system-definition android:name="DTMB"
-        android:country="CN">
-        <rating-definition android:name="DTMB_4"
-            android:title="4"
-            android:description="@string/description_age_4"
-            android:contentAgeHint="4" />
-        <rating-definition android:name="DTMB_5"
-            android:title="5"
-            android:description="@string/description_age_5"
-            android:contentAgeHint="5" />
-        <rating-definition android:name="DTMB_6"
-            android:title="6"
-            android:description="@string/description_age_6"
-            android:contentAgeHint="6" />
-        <rating-definition android:name="DTMB_7"
-            android:title="7"
-            android:description="@string/description_age_7"
-            android:contentAgeHint="7" />
-        <rating-definition android:name="DTMB_8"
-            android:title="8"
-            android:description="@string/description_age_8"
-            android:contentAgeHint="8" />
-        <rating-definition android:name="DTMB_9"
-            android:title="9"
-            android:description="@string/description_age_9"
-            android:contentAgeHint="9" />
-        <rating-definition android:name="DTMB_10"
-            android:title="10"
-            android:description="@string/description_age_10"
-            android:contentAgeHint="10" />
-        <rating-definition android:name="DTMB_11"
-            android:title="11"
-            android:description="@string/description_age_11"
-            android:contentAgeHint="11" />
-        <rating-definition android:name="DTMB_12"
-            android:title="12"
-            android:description="@string/description_age_12"
-            android:contentAgeHint="12" />
-        <rating-definition android:name="DTMB_13"
-            android:title="13"
-            android:description="@string/description_age_13"
-            android:contentAgeHint="13" />
-        <rating-definition android:name="DTMB_14"
-            android:title="14"
-            android:description="@string/description_age_14"
-            android:contentAgeHint="14" />
-        <rating-definition android:name="DTMB_15"
-            android:title="15"
-            android:description="@string/description_age_15"
-            android:contentAgeHint="15" />
-        <rating-definition android:name="DTMB_16"
-            android:title="16"
-            android:description="@string/description_age_16"
-            android:contentAgeHint="16" />
-        <rating-definition android:name="DTMB_17"
-            android:title="17"
-            android:description="@string/description_age_17"
-            android:contentAgeHint="17" />
-        <rating-definition android:name="DTMB_18"
-            android:title="18"
-            android:description="@string/description_age_18"
-            android:contentAgeHint="18" />
-        <rating-order>
-            <rating android:name="DTMB_4" />
-            <rating android:name="DTMB_5" />
-            <rating android:name="DTMB_6" />
-            <rating android:name="DTMB_7" />
-            <rating android:name="DTMB_8" />
-            <rating android:name="DTMB_9" />
-            <rating android:name="DTMB_10" />
-            <rating android:name="DTMB_11" />
-            <rating android:name="DTMB_12" />
-            <rating android:name="DTMB_13" />
-            <rating android:name="DTMB_14" />
-            <rating android:name="DTMB_15" />
-            <rating android:name="DTMB_16" />
-            <rating android:name="DTMB_17" />
-            <rating android:name="DTMB_18" />
-        </rating-order>
-    </rating-system-definition>
-
-    <!-- TV content rating system for DTMB. See http://www.gb688.cn/bzgk/gb/newGbInfo?hcno=59E83CA701AEB4248E115BC043688FEC -->
-    <rating-system-definition android:name="DTMB"
-        android:country="CN">
-        <rating-definition android:name="DTMB_4"
-            android:title="4"
-            android:description="@string/description_age_4"
-            android:contentAgeHint="4" />
-        <rating-definition android:name="DTMB_5"
-            android:title="5"
-            android:description="@string/description_age_5"
-            android:contentAgeHint="5" />
-        <rating-definition android:name="DTMB_6"
-            android:title="6"
-            android:description="@string/description_age_6"
-            android:contentAgeHint="6" />
-        <rating-definition android:name="DTMB_7"
-            android:title="7"
-            android:description="@string/description_age_7"
-            android:contentAgeHint="7" />
-        <rating-definition android:name="DTMB_8"
-            android:title="8"
-            android:description="@string/description_age_8"
-            android:contentAgeHint="8" />
-        <rating-definition android:name="DTMB_9"
-            android:title="9"
-            android:description="@string/description_age_9"
-            android:contentAgeHint="9" />
-        <rating-definition android:name="DTMB_10"
-            android:title="10"
-            android:description="@string/description_age_10"
-            android:contentAgeHint="10" />
-        <rating-definition android:name="DTMB_11"
-            android:title="11"
-            android:description="@string/description_age_11"
-            android:contentAgeHint="11" />
-        <rating-definition android:name="DTMB_12"
-            android:title="12"
-            android:description="@string/description_age_12"
-            android:contentAgeHint="12" />
-        <rating-definition android:name="DTMB_13"
-            android:title="13"
-            android:description="@string/description_age_13"
-            android:contentAgeHint="13" />
-        <rating-definition android:name="DTMB_14"
-            android:title="14"
-            android:description="@string/description_age_14"
-            android:contentAgeHint="14" />
-        <rating-definition android:name="DTMB_15"
-            android:title="15"
-            android:description="@string/description_age_15"
-            android:contentAgeHint="15" />
-        <rating-definition android:name="DTMB_16"
-            android:title="16"
-            android:description="@string/description_age_16"
-            android:contentAgeHint="16" />
-        <rating-definition android:name="DTMB_17"
-            android:title="17"
-            android:description="@string/description_age_17"
-            android:contentAgeHint="17" />
-        <rating-definition android:name="DTMB_18"
-            android:title="18"
-            android:description="@string/description_age_18"
-            android:contentAgeHint="18" />
-        <rating-order>
-            <rating android:name="DTMB_4" />
-            <rating android:name="DTMB_5" />
-            <rating android:name="DTMB_6" />
-            <rating android:name="DTMB_7" />
-            <rating android:name="DTMB_8" />
-            <rating android:name="DTMB_9" />
-            <rating android:name="DTMB_10" />
-            <rating android:name="DTMB_11" />
-            <rating android:name="DTMB_12" />
-            <rating android:name="DTMB_13" />
-            <rating android:name="DTMB_14" />
-            <rating android:name="DTMB_15" />
-            <rating android:name="DTMB_16" />
-            <rating android:name="DTMB_17" />
-            <rating android:name="DTMB_18" />
-        </rating-order>
-    </rating-system-definition>
-
     <!-- TV content rating system for DVB. See Table 81 of DVB SI (EN 300 468 V1.14.1) in https://www.dvb.org/standards -->
     <rating-system-definition android:name="DVB"
         android:country="AM, BG, CH, DE, DK, FI, GR, HU, ID, IE, IL, IS, MY, NL, NZ, PL, PT, RO, RU, RS, SI, TH, TR, TW, UA">
@@ -840,28 +676,6 @@
         </rating-order>
     </rating-system-definition>
 
-    <!-- TV content rating system for NZ. See http://www.freeviewnz.tv/ -->
-    <rating-system-definition android:name="NZ_TV"
-        android:country="NZ">
-        <rating-definition android:name="NZ_TV_G"
-            android:title="G"
-            android:description="@string/description_nz_fta_tv_g"
-            android:contentAgeHint="0" />
-        <rating-definition android:name="NZ_TV_PGR"
-            android:title="PGR"
-            android:description="@string/description_nz_fta_tv_pgr"
-            android:contentAgeHint="0" />
-        <rating-definition android:name="NZ_TV_AO"
-            android:title="AO"
-            android:description="@string/description_nz_fta_tv_ao"
-            android:contentAgeHint="0" />
-        <rating-order>
-            <rating android:name="NZ_TV_G" />
-            <rating android:name="NZ_TV_PGR" />
-            <rating android:name="NZ_TV_AO" />
-        </rating-order>
-    </rating-system-definition>
-
     <!-- TV content rating system for SG. See http://www.mda.gov.sg/RegulationsAndLicensing/ContentStandardsAndClassification/FilmsAndVideos/Pages/default.aspx -->
     <rating-system-definition android:name="SG_TV"
         android:country="SG">
@@ -899,43 +713,6 @@
         </rating-order>
     </rating-system-definition>
 
-    <!-- TV content rating system for TH. See https://broadcast.nbtc.go.th/home/ -->
-    <rating-system-definition android:name="TH_TV"
-        android:country="TH">
-        <rating-definition android:name="TH_TV_4"
-            android:title="4"
-            android:description="@string/description_th_tv_4"
-            android:contentAgeHint="4" />
-        <rating-definition android:name="TH_TV_6"
-            android:title="6"
-            android:description="@string/description_th_tv_6"
-            android:contentAgeHint="6" />
-        <rating-definition android:name="TH_TV_10"
-            android:title="10"
-            android:description="@string/description_th_tv_10"
-            android:contentAgeHint="10" />
-        <rating-definition android:name="TH_TV_13"
-            android:title="13"
-            android:description="@string/description_th_tv_13"
-            android:contentAgeHint="13" />
-        <rating-definition android:name="TH_TV_18"
-            android:title="18"
-            android:description="@string/description_th_tv_18"
-            android:contentAgeHint="18" />
-        <rating-definition android:name="TH_TV_19"
-            android:title="19"
-            android:description="@string/description_th_tv_19"
-            android:contentAgeHint="19" />
-        <rating-order>
-            <rating android:name="TH_TV_4" />
-            <rating android:name="TH_TV_6" />
-            <rating android:name="TH_TV_10" />
-            <rating android:name="TH_TV_13" />
-            <rating android:name="TH_TV_18" />
-            <rating android:name="TH_TV_19" />
-        </rating-order>
-    </rating-system-definition>
-
     <!-- TV content rating system for US. See http://www.tvguidelines.org/ratings.htm -->
     <rating-system-definition android:name="US_TV"
         android:country="US">
diff --git a/settings.gradle b/settings.gradle
index 5916cb4..6d5cb54 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -23,5 +23,3 @@
 include ':tuner'
 include ':SampleDvbTuner'
 project(":SampleDvbTuner").projectDir = file("tuner/SampleDvbTuner")
-include ':SampleNetworkTuner'
-project(":SampleNetworkTuner").projectDir = file("tuner/SampleNetworkTuner")
diff --git a/src/com/android/tv/LauncherActivity.java b/src/com/android/tv/LauncherActivity.java
index ccc5600..679d612 100644
--- a/src/com/android/tv/LauncherActivity.java
+++ b/src/com/android/tv/LauncherActivity.java
@@ -27,10 +27,10 @@
  * An activity to launch a new activity.
  *
  * <p>In the case when {@link MainActivity} starts a new activity using {@link
- * Activity#startActivity} or {@link Activity#startActivityForResult}, TV app is terminated if the
- * new activity crashes. That's because the {@link android.app.ActivityManager} terminates the
- * activity which is just below the crashed activity in the activity stack. To avoid this, we need
- * to locate an additional activity between these activities in the activity stack.
+ * Activity#startActivity} or {@link Activity#startActivityForResult}, Live TV app is
+ * terminated if the new activity crashes. That's because the {@link android.app.ActivityManager}
+ * terminates the activity which is just below the crashed activity in the activity stack. To avoid
+ * this, we need to locate an additional activity between these activities in the activity stack.
  */
 public class LauncherActivity extends Activity {
     private static final String TAG = "LauncherActivity";
diff --git a/src/com/android/tv/MainActivity.java b/src/com/android/tv/MainActivity.java
index 7a59150..b4cf71d 100644
--- a/src/com/android/tv/MainActivity.java
+++ b/src/com/android/tv/MainActivity.java
@@ -16,8 +16,6 @@
 
 package com.android.tv;
 
-import static com.android.tv.common.feature.SystemAppFeature.SYSTEM_APP_FEATURE;
-
 import android.app.Activity;
 import android.app.PendingIntent;
 import android.app.SearchManager;
@@ -46,7 +44,6 @@
 import android.os.Handler;
 import android.os.Message;
 import android.os.PowerManager;
-import android.provider.BaseColumns;
 import android.provider.Settings;
 import android.support.annotation.IntDef;
 import android.support.annotation.NonNull;
@@ -68,7 +65,6 @@
 import android.view.accessibility.AccessibilityManager;
 import android.widget.FrameLayout;
 import android.widget.Toast;
-
 import com.android.tv.MainActivity.MySingletons;
 import com.android.tv.analytics.SendChannelStatusRunnable;
 import com.android.tv.analytics.SendConfigInfoRunnable;
@@ -82,7 +78,6 @@
 import com.android.tv.common.TvContentRatingCache;
 import com.android.tv.common.WeakHandler;
 import com.android.tv.common.compat.TvInputInfoCompat;
-import com.android.tv.common.dev.DeveloperPreferences;
 import com.android.tv.common.feature.CommonFeatures;
 import com.android.tv.common.memory.MemoryManageable;
 import com.android.tv.common.singletons.HasSingletons;
@@ -96,13 +91,11 @@
 import com.android.tv.data.ChannelDataManager;
 import com.android.tv.data.ChannelImpl;
 import com.android.tv.data.OnCurrentProgramUpdatedListener;
+import com.android.tv.data.Program;
 import com.android.tv.data.ProgramDataManager;
-import com.android.tv.data.ProgramImpl;
 import com.android.tv.data.StreamInfo;
 import com.android.tv.data.WatchedHistoryManager;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
-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;
@@ -113,12 +106,11 @@
 import com.android.tv.dvr.ui.DvrStopRecordingFragment;
 import com.android.tv.dvr.ui.DvrUiHelper;
 import com.android.tv.features.TvFeatures;
-import com.android.tv.guide.ProgramItemView;
 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.perf.StartupMeasureFactory;
+import com.android.tv.perf.PerformanceMonitorManagerFactory;
 import com.android.tv.receiver.AudioCapabilitiesReceiver;
 import com.android.tv.recommendation.ChannelPreviewUpdater;
 import com.android.tv.recommendation.NotificationService;
@@ -134,7 +126,6 @@
 import com.android.tv.ui.TunableTvView.BlockScreenType;
 import com.android.tv.ui.TunableTvView.OnTuneListener;
 import com.android.tv.ui.TvOverlayManager;
-import com.android.tv.ui.TvOverlayManagerFactory;
 import com.android.tv.ui.TvViewUiManager;
 import com.android.tv.ui.sidepanel.ClosedCaptionFragment;
 import com.android.tv.ui.sidepanel.CustomizeChannelListFragment;
@@ -144,7 +135,6 @@
 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.ui.sidepanel.parentalcontrols.RatingsFragment;
 import com.android.tv.util.AsyncDbTask;
 import com.android.tv.util.AsyncDbTask.DbExecutor;
 import com.android.tv.util.CaptionSettings;
@@ -160,17 +150,9 @@
 import com.android.tv.util.images.ImageCache;
 
 import com.google.common.base.Optional;
-
 import dagger.android.AndroidInjection;
-import dagger.android.AndroidInjector;
 import dagger.android.ContributesAndroidInjector;
-import dagger.android.DispatchingAndroidInjector;
-import dagger.android.HasAndroidInjector;
-
 import com.android.tv.common.flags.BackendKnobsFlags;
-import com.android.tv.common.flags.LegacyFlags;
-import com.android.tv.common.flags.StartupFlags;
-
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayDeque;
@@ -181,17 +163,15 @@
 import java.util.Set;
 import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
-
 import javax.inject.Inject;
 import javax.inject.Provider;
 
-/** The main activity for the TV app. */
+/** The main activity for the Live TV app. */
 public class MainActivity extends Activity
         implements OnActionClickListener,
                 OnPinCheckedListener,
                 ChannelChanger,
-                HasSingletons<MySingletons>,
-                HasAndroidInjector {
+                HasSingletons<MySingletons> {
     private static final String TAG = "MainActivity";
     private static final boolean DEBUG = false;
     private AudioCapabilitiesReceiver mAudioCapabilitiesReceiver;
@@ -278,11 +258,10 @@
     private static final long START_UP_TIMER_RESET_THRESHOLD_MS = TimeUnit.SECONDS.toMillis(3);
 
     {
-        StartupMeasureFactory.create().onActivityInit();
+        PerformanceMonitorManagerFactory.create().getStartupMeasure().onActivityInit();
     }
 
     private final MySingletonsImpl mMySingletons = new MySingletonsImpl();
-    @Inject DispatchingAndroidInjector<Object> mAndroidInjector;
     @Inject @DbExecutor Executor mDbExecutor;
 
     private AccessibilityManager mAccessibilityManager;
@@ -299,12 +278,8 @@
     private DvrManager mDvrManager;
     private ConflictChecker mDvrConflictChecker;
     @Inject BackendKnobsFlags mBackendKnobs;
-    @Inject LegacyFlags mLegacyFlags;
-    @Inject StartupFlags mStartupFlags;
     @Inject SetupUtils mSetupUtils;
     @Inject Optional<BuiltInTunerManager> mOptionalBuiltInTunerManager;
-    @Inject AccountHelper mAccountHelper;
-    @Inject EpgFetcher mEpgFetcher;
 
     @VisibleForTesting protected TunableTvView mTvView;
     private View mContentView;
@@ -339,7 +314,6 @@
     private boolean mIsFilmModeSet;
     private float mDefaultRefreshRate;
 
-    @Inject TvOverlayManagerFactory mOverlayFactory;
     private TvOverlayManager mOverlayManager;
 
     // mIsCurrentChannelUnblockedByUser and mWasChannelUnblockedBeforeShrunkenByUser are used for
@@ -503,6 +477,7 @@
         AndroidInjection.inject(this);
         mAccessibilityManager =
                 (AccessibilityManager) getSystemService(Context.ACCESSIBILITY_SERVICE);
+        TvSingletons tvSingletons = TvSingletons.getSingletons(this);
         DurationTimer startUpDebugTimer = Debug.getTimer(Debug.TAG_START_UP_TIMER);
         if (!startUpDebugTimer.isStarted()
                 || startUpDebugTimer.getDuration() > START_UP_TIMER_RESET_THRESHOLD_MS) {
@@ -521,7 +496,6 @@
             finishAndRemoveTask();
             return;
         }
-        mAccountHelper.init();
 
         TvSingletons tvApplication = (TvSingletons) getApplication();
         // In API 23, TvContract.isChannelUriForPassthroughInput is hidden.
@@ -540,8 +514,8 @@
             return;
         }
         setContentView(R.layout.activity_tv);
-        mTvView = findViewById(R.id.main_tunable_tv_view);
-        mTvView.initialize(mProgramDataManager, mTvInputManagerHelper, mLegacyFlags);
+        mTvView = (TunableTvView) findViewById(R.id.main_tunable_tv_view);
+        mTvView.initialize(mProgramDataManager, mTvInputManagerHelper);
         mTvView.setOnUnhandledInputEventListener(
                 new OnUnhandledInputEventListener() {
                     @Override
@@ -571,13 +545,12 @@
         String inputId = Utils.getLastWatchedTunerInputId(this);
         if (!isPassthroughInput
                 && inputId != null
-                && !mStartupFlags.warmupInputidBlacklist().getElementList().contains(inputId)
                 && channelId != Channel.INVALID_ID) {
             mTvView.warmUpInput(inputId, TvContract.buildChannelUri(channelId));
         }
 
         tvApplication.getMainActivityWrapper().onMainActivityCreated(this);
-        if (BuildConfig.ENG && DeveloperPreferences.ALLOW_STRICT_MODE.get(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();
@@ -639,10 +612,13 @@
         }
         mTvViewUiManager =
                 new TvViewUiManager(
-                        this, mTvView, findViewById(android.R.id.content), mTvOptionsManager);
+                        this,
+                        mTvView,
+                        (FrameLayout) findViewById(android.R.id.content),
+                        mTvOptionsManager);
 
         mContentView = findViewById(android.R.id.content);
-        ViewGroup sceneContainer = findViewById(R.id.scene_container);
+        ViewGroup sceneContainer = (ViewGroup) findViewById(R.id.scene_container);
         ChannelBannerView channelBannerView =
                 (ChannelBannerView)
                         getLayoutInflater().inflate(R.layout.channel_banner, sceneContainer, false);
@@ -695,7 +671,7 @@
                 });
         mSearchFragment = new ProgramGuideSearchFragment();
         mOverlayManager =
-                mOverlayFactory.create(
+                new TvOverlayManager(
                         this,
                         mChannelTuner,
                         mTvView,
@@ -733,6 +709,8 @@
                 SendChannelStatusRunnable.startChannelStatusRecurringRunner(
                         this, mTracker, mChannelDataManager);
 
+        // To avoid not updating Rating systems when changing language.
+        mTvInputManagerHelper.getContentRatingsManager().update();
         if (CommonFeatures.DVR.isEnabled(this)
                 && TvFeatures.SHOW_UPCOMING_CONFLICT_DIALOG.isEnabled(this)) {
             mDvrConflictChecker = new ConflictChecker(this);
@@ -764,7 +742,7 @@
                 mChannelDataManager.reload();
                 mProgramDataManager.reload();
 
-                // Restart TV app.
+                // Restart live channels.
                 Intent intent = getIntent();
                 finish();
                 startActivity(intent);
@@ -852,7 +830,7 @@
                     .getTunerInputController()
                     .executeNetworkTunerDiscoveryAsyncTask(this);
         }
-        mEpgFetcher.fetchImmediatelyIfNeeded();
+        TvSingletons.getSingletons(this).getEpgFetcher().fetchImmediatelyIfNeeded();
     }
 
     @Override
@@ -1149,8 +1127,8 @@
             Toast.makeText(this, R.string.msg_no_setup_activity, Toast.LENGTH_SHORT).show();
             return;
         }
-        // Even though other app can handle the intent, the setup launched by TV app
-        // should go through TV app SetupPassthroughActivity.
+        // Even though other app can handle the intent, the setup launched by Live channels
+        // should go through Live channels SetupPassthroughActivity.
         intent.setComponent(new ComponentName(this, SetupPassthroughActivity.class));
         try {
             // Now we know that the user intends to set up this input. Grant permission for writing
@@ -1420,9 +1398,7 @@
 
     @Override
     public boolean dispatchKeyEvent(KeyEvent event) {
-        if (DeveloperPreferences.LOG_KEYEVENT.get(this)) {
-            Log.d(TAG, "dispatchKeyEvent(" + event + ")");
-        }
+        if (SystemProperties.LOG_KEYEVENT.getValue()) Log.d(TAG, "dispatchKeyEvent(" + event + ")");
         // If an activity is closed on a back key down event, back key down events with none zero
         // repeat count or a back key up event can be happened without the first back key down
         // event which should be ignored in this activity.
@@ -1527,7 +1503,7 @@
                 new AsyncQueryProgramTask(
                                 mDbExecutor,
                                 programUriFromIntent,
-                                ProgramImpl.PROJECTION,
+                                Program.PROJECTION,
                                 null,
                                 null,
                                 null,
@@ -1558,7 +1534,7 @@
                 String inputId = mInitChannelUri.getQueryParameter("input");
                 long channelId = Utils.getLastWatchedChannelIdForInput(this, inputId);
                 if (channelId == Channel.INVALID_ID) {
-                    String[] projection = {BaseColumns._ID};
+                    String[] projection = {Channels._ID};
                     long time = System.currentTimeMillis();
                     try (Cursor cursor =
                             getContentResolver().query(uri, projection, null, null, null)) {
@@ -1606,7 +1582,7 @@
         protected Program onQuery(Cursor c) {
             Program program = null;
             if (c != null && c.moveToNext()) {
-                program = ProgramImpl.fromCursor(c);
+                program = Program.fromCursor(c);
             }
             return program;
         }
@@ -1622,7 +1598,7 @@
                 Intent intent = new Intent(MainActivity.this, DetailsActivity.class);
                 intent.putExtra(DetailsActivity.CHANNEL_ID, mChannelIdFromIntent);
                 intent.putExtra(DetailsActivity.DETAILS_VIEW_TYPE, DetailsActivity.PROGRAM_VIEW);
-                intent.putExtra(DetailsActivity.PROGRAM, program.toParcelable());
+                intent.putExtra(DetailsActivity.PROGRAM, program);
                 intent.putExtra(DetailsActivity.INPUT_ID, channel.getInputId());
                 startActivity(intent);
             }
@@ -2101,7 +2077,7 @@
 
     @Override
     public boolean onKeyDown(int keyCode, KeyEvent event) {
-        if (DeveloperPreferences.LOG_KEYEVENT.get(this)) {
+        if (SystemProperties.LOG_KEYEVENT.getValue()) {
             Log.d(TAG, "onKeyDown(" + keyCode + ", " + event + ")");
         }
         switch (mOverlayManager.onKeyDown(keyCode, event)) {
@@ -2191,7 +2167,7 @@
          *  W debug: toggle screen size
          *  V KEYCODE_MEDIA_RECORD debug: record the current channel for 30 sec
          */
-        if (DeveloperPreferences.LOG_KEYEVENT.get(this)) {
+        if (SystemProperties.LOG_KEYEVENT.getValue()) {
             Log.d(TAG, "onKeyUp(" + keyCode + ", " + event + ")");
         }
         // If we are in the middle of channel change, finish it before showing overlays.
@@ -2289,7 +2265,7 @@
                     // Channel change is already done in the head of this method.
                     return true;
                 case KeyEvent.KEYCODE_S:
-                    if (!DeveloperPreferences.USE_DEBUG_KEYS.get(this)) {
+                    if (!SystemProperties.USE_DEBUG_KEYS.getValue()) {
                         break;
                     }
                     // fall through.
@@ -2297,7 +2273,7 @@
                     mOverlayManager.getSideFragmentManager().show(new ClosedCaptionFragment());
                     return true;
                 case KeyEvent.KEYCODE_A:
-                    if (!DeveloperPreferences.USE_DEBUG_KEYS.get(this)) {
+                    if (!SystemProperties.USE_DEBUG_KEYS.getValue()) {
                         break;
                     }
                     // fall through.
@@ -2363,7 +2339,7 @@
             // in case that TV isn't showing properly (e.g. no browsable channel)
             return true;
         }
-        if (DeveloperPreferences.USE_DEBUG_KEYS.get(this) || BuildConfig.ENG) {
+        if (SystemProperties.USE_DEBUG_KEYS.getValue() || BuildConfig.ENG) {
             switch (keyCode) {
                 case KeyEvent.KEYCODE_W:
                     mDebugNonFullSizeScreen = !mDebugNonFullSizeScreen;
@@ -2419,7 +2395,7 @@
 
     @Override
     public boolean onKeyLongPress(int keyCode, KeyEvent event) {
-        if (DeveloperPreferences.LOG_KEYEVENT.get(this)) Log.d(TAG, "onKeyLongPress(" + event);
+        if (SystemProperties.LOG_KEYEVENT.getValue()) Log.d(TAG, "onKeyLongPress(" + event);
         if (USE_BACK_KEY_LONG_PRESS) {
             // Treat the BACK key long press as the normal press since we changed the behavior in
             // onBackPressed().
@@ -2489,7 +2465,7 @@
     }
 
     private boolean dispatchKeyEventToSession(final KeyEvent event) {
-        if (DeveloperPreferences.LOG_KEYEVENT.get(this)) {
+        if (SystemProperties.LOG_KEYEVENT.getValue()) {
             Log.d(TAG, "dispatchKeyEventToSession(" + event + ")");
         }
         boolean handled = false;
@@ -2742,10 +2718,7 @@
             return;
         }
 
-        // Only try to set the channels browseable if we are a system app.
-        if (SYSTEM_APP_FEATURE.isEnabled(getApplicationContext())) {
-            Utils.enableAllChannels(this);
-        }
+        Utils.enableAllChannels(this);
     }
 
     // Lazy initialization
@@ -2805,11 +2778,6 @@
         }
     }
 
-    @Override
-    public AndroidInjector<Object> androidInjector() {
-        return mAndroidInjector;
-    }
-
     private static class MainActivityHandler extends WeakHandler<MainActivity> {
         MainActivityHandler(MainActivity mainActivity) {
             super(mainActivity);
@@ -2855,8 +2823,11 @@
             Debug.getTimer(Debug.TAG_START_UP_TIMER).log("MainActivity.MyOnTuneListener.onTune");
             mChannel = channel;
             mWasUnderShrunkenTvView = wasUnderShrunkenTvView;
-            // Fetch complete projection of tuned channel.
-            mProgramDataManager.onChannelTuned(channel.getId());
+
+            if (mBackendKnobs.enablePartialProgramFetch()) {
+                // Fetch complete projection of tuned channel.
+                mProgramDataManager.prefetchChannel(channel.getId());
+            }
         }
 
         @Override
@@ -3011,14 +2982,5 @@
     public abstract static class Module {
         @ContributesAndroidInjector
         abstract MainActivity contributesMainActivityActivityInjector();
-
-        @ContributesAndroidInjector
-        abstract DeveloperOptionFragment contributesDeveloperOptionFragment();
-
-        @ContributesAndroidInjector
-        abstract RatingsFragment contributesRatingsFragment();
-
-        @ContributesAndroidInjector
-        abstract ProgramItemView contributesProgramItemView();
     }
 }
diff --git a/src/com/android/tv/MediaSessionWrapper.java b/src/com/android/tv/MediaSessionWrapper.java
index df88639..a647a06 100644
--- a/src/com/android/tv/MediaSessionWrapper.java
+++ b/src/com/android/tv/MediaSessionWrapper.java
@@ -34,9 +34,8 @@
 import android.support.annotation.VisibleForTesting;
 import android.text.TextUtils;
 import android.util.Log;
-
+import com.android.tv.data.Program;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
 import com.android.tv.util.Utils;
 import com.android.tv.util.images.ImageLoader;
 
diff --git a/src/com/android/tv/SetupPassthroughActivity.java b/src/com/android/tv/SetupPassthroughActivity.java
index 25049f1..5185b12 100644
--- a/src/com/android/tv/SetupPassthroughActivity.java
+++ b/src/com/android/tv/SetupPassthroughActivity.java
@@ -18,7 +18,7 @@
 
 import android.app.Activity;
 import android.content.ActivityNotFoundException;
-import android.content.ComponentName;
+import android.content.Context;
 import android.content.Intent;
 import android.media.tv.TvInputInfo;
 import android.os.Bundle;
@@ -26,8 +26,6 @@
 import android.os.Looper;
 import android.support.annotation.MainThread;
 import android.util.Log;
-
-import com.android.tv.common.CommonConstants;
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.common.actions.InputSetupActionUtils;
 import com.android.tv.data.ChannelDataManager;
@@ -38,16 +36,9 @@
 import com.android.tv.util.SetupUtils;
 import com.android.tv.util.TvInputManagerHelper;
 import com.android.tv.util.Utils;
-
 import com.google.android.tv.partner.support.EpgContract;
-
-import dagger.android.AndroidInjection;
-import dagger.android.ContributesAndroidInjector;
-
 import java.util.concurrent.TimeUnit;
 
-import javax.inject.Inject;
-
 /**
  * An activity to launch a TV input setup activity.
  *
@@ -64,20 +55,18 @@
     private TvInputInfo mTvInputInfo;
     private Intent mActivityAfterCompletion;
     private boolean mEpgFetcherDuringScan;
-    @Inject EpgInputWhiteList mEpgInputWhiteList;
-    @Inject TvInputManagerHelper mInputManager;
-    @Inject SetupUtils mSetupUtils;
-    @Inject ChannelDataManager mChannelDataManager;
-    @Inject EpgFetcher mEpgFetcher;
+    private EpgInputWhiteList mEpgInputWhiteList;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
         if (DEBUG) Log.d(TAG, "onCreate");
-        AndroidInjection.inject(this);
         super.onCreate(savedInstanceState);
+        TvSingletons tvSingletons = TvSingletons.getSingletons(this);
+        TvInputManagerHelper inputManager = tvSingletons.getTvInputManagerHelper();
         Intent intent = getIntent();
         String inputId = intent.getStringExtra(InputSetupActionUtils.EXTRA_INPUT_ID);
-        mTvInputInfo = mInputManager.getTvInputInfo(inputId);
+        mTvInputInfo = inputManager.getTvInputInfo(inputId);
+        mEpgInputWhiteList = new EpgInputWhiteList(tvSingletons.getCloudEpgFlags());
         mActivityAfterCompletion = InputSetupActionUtils.getExtraActivityAfter(intent);
         boolean needToFetchEpg =
                 mTvInputInfo != null && Utils.isInternalTvInput(this, mTvInputInfo.getId());
@@ -117,17 +106,6 @@
             InputSetupActionUtils.removeSetupIntent(extras);
             setupIntent.putExtras(extras);
             try {
-                ComponentName callingActivity = getCallingActivity();
-                if (callingActivity != null
-                        && !callingActivity.getPackageName().equals(CommonConstants.BASE_PACKAGE)) {
-                    Log.w(
-                            TAG,
-                            "Calling activity "
-                                    + callingActivity.getPackageName()
-                                    + " is not trusted. Not forwarding intent.");
-                    finish();
-                    return;
-                }
                 startActivityForResult(setupIntent, REQUEST_START_SETUP_ACTIVITY);
             } catch (ActivityNotFoundException e) {
                 Log.e(TAG, "Can't find activity: " + setupIntent.getComponent());
@@ -136,10 +114,10 @@
             }
             if (needToFetchEpg) {
                 if (sScanTimeoutMonitor == null) {
-                    sScanTimeoutMonitor = new ScanTimeoutMonitor(mEpgFetcher, mChannelDataManager);
+                    sScanTimeoutMonitor = new ScanTimeoutMonitor(this);
                 }
                 sScanTimeoutMonitor.startMonitoring();
-                mEpgFetcher.onChannelScanStarted();
+                TvSingletons.getSingletons(this).getEpgFetcher().onChannelScanStarted();
             }
         }
     }
@@ -155,25 +133,15 @@
         boolean setupComplete =
                 requestCode == REQUEST_START_SETUP_ACTIVITY && resultCode == Activity.RESULT_OK;
         // Tells EpgFetcher that channel source setup is finished.
-
+        EpgFetcher epgFetcher = TvSingletons.getSingletons(this).getEpgFetcher();
         if (mEpgFetcherDuringScan) {
-            mEpgFetcher.onChannelScanFinished();
+            epgFetcher.onChannelScanFinished();
         }
         if (!setupComplete) {
             setResult(resultCode, data);
             finish();
             return;
         }
-        if (TvFeatures.CLOUD_EPG_FOR_3RD_PARTY.isEnabled(this)
-                && data != null
-                && data.getBooleanExtra(EpgContract.EXTRA_USE_CLOUD_EPG, false)) {
-            if (DEBUG) Log.d(TAG, "extra " + data.getExtras());
-            String inputId = data.getStringExtra(TvInputInfo.EXTRA_INPUT_ID);
-            if (mEpgInputWhiteList.isInputWhiteListed(inputId)) {
-                mEpgFetcher.fetchImmediately();
-            }
-        }
-
         if (mTvInputInfo == null) {
             Log.w(
                     TAG,
@@ -184,19 +152,21 @@
             finish();
             return;
         }
-        mSetupUtils.onTvInputSetupFinished(
-                mTvInputInfo.getId(),
-                () -> {
-                    if (mActivityAfterCompletion != null) {
-                        try {
-                            startActivity(mActivityAfterCompletion);
-                        } catch (ActivityNotFoundException e) {
-                            Log.w(TAG, "Activity launch failed", e);
-                        }
-                    }
-                    setResult(resultCode, data);
-                    finish();
-                });
+        TvSingletons.getSingletons(this)
+                .getSetupUtils()
+                .onTvInputSetupFinished(
+                        mTvInputInfo.getId(),
+                        () -> {
+                            if (mActivityAfterCompletion != null) {
+                                try {
+                                    startActivity(mActivityAfterCompletion);
+                                } catch (ActivityNotFoundException e) {
+                                    Log.w(TAG, "Activity launch failed", e);
+                                }
+                            }
+                            setResult(resultCode, data);
+                            finish();
+                        });
     }
 
     /**
@@ -209,7 +179,7 @@
         // 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 EpgFetcher mEpgFetcher;
+        private final Context mContext;
         private final ChannelDataManager mChannelDataManager;
         private final Handler mHandler = new Handler(Looper.getMainLooper());
         private final Runnable mScanTimeoutRunnable =
@@ -237,9 +207,9 @@
                 };
         private boolean mStarted;
 
-        private ScanTimeoutMonitor(EpgFetcher epgFetcher, ChannelDataManager mChannelDataManager) {
-            mEpgFetcher = epgFetcher;
-            this.mChannelDataManager = mChannelDataManager;
+        private ScanTimeoutMonitor(Context context) {
+            mContext = context.getApplicationContext();
+            mChannelDataManager = TvSingletons.getSingletons(context).getChannelDataManager();
         }
 
         private void startMonitoring() {
@@ -267,14 +237,7 @@
 
         private void onScanTimedOut() {
             stopMonitoring();
-            mEpgFetcher.onChannelScanFinished();
+            TvSingletons.getSingletons(mContext).getEpgFetcher().onChannelScanFinished();
         }
     }
-
-    /** Exports {@link MainActivity} for Dagger codegen to create the appropriate injector. */
-    @dagger.Module
-    public abstract static class Module {
-        @ContributesAndroidInjector
-        abstract SetupPassthroughActivity contributesSetupPassthroughActivity();
-    }
 }
diff --git a/src/com/android/tv/TimeShiftManager.java b/src/com/android/tv/TimeShiftManager.java
index f08b5e8..779e8df 100644
--- a/src/com/android/tv/TimeShiftManager.java
+++ b/src/com/android/tv/TimeShiftManager.java
@@ -26,21 +26,18 @@
 import android.support.annotation.VisibleForTesting;
 import android.util.Log;
 import android.util.Range;
-
 import com.android.tv.analytics.Tracker;
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.common.WeakHandler;
 import com.android.tv.data.OnCurrentProgramUpdatedListener;
+import com.android.tv.data.Program;
 import com.android.tv.data.ProgramDataManager;
-import com.android.tv.data.ProgramImpl;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
 import com.android.tv.ui.TunableTvView;
 import com.android.tv.ui.api.TunableTvViewPlayingApi.TimeShiftListener;
 import com.android.tv.util.AsyncDbTask;
 import com.android.tv.util.TimeShiftUtils;
 import com.android.tv.util.Utils;
-
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
@@ -53,7 +50,7 @@
 import java.util.concurrent.TimeUnit;
 
 /**
- * A class which manages the time shift feature in TV app. It consists of two parts. {@link
+ * A class which manages the time shift feature in Live TV. It consists of two parts. {@link
  * PlayController} controls the playback such as play/pause, rewind and fast-forward using {@link
  * TunableTvView} which communicates with TvInputService through {@link
  * android.media.tv.TvInputService.Session}. {@link ProgramManager} loads programs of the current
@@ -147,8 +144,8 @@
             DISABLE_ACTION_THRESHOLD + 3 * REQUEST_CURRENT_POSITION_INTERVAL;
     /**
      * The current position sent from TIS can not be exactly the same as the current system time due
-     * to the elapsed time to pass the message from TIS to TV app. So the boundary threshold is
-     * necessary. The same goes for the recording start time. It's the same {@link
+     * to the elapsed time to pass the message from TIS to Live TV. So the boundary threshold
+     * is necessary. The same goes for the recording start time. It's the same {@link
      * #REQUEST_CURRENT_POSITION_INTERVAL}.
      */
     private static final long RECORDING_BOUNDARY_THRESHOLD = REQUEST_CURRENT_POSITION_INTERVAL;
@@ -622,8 +619,8 @@
                                     < mAvailablityChangedTimeMs - ALLOWED_START_TIME_OFFSET) {
                                 Log.e(
                                         TAG,
-                                        "The start time is too earlier than the time of"
-                                                + " availability: {startTime: "
+                                        "The start time is too earlier than the time of availability: {"
+                                                + "startTime: "
                                                 + recordStartTimeMs
                                                 + ", availability: "
                                                 + mAvailablityChangedTimeMs);
@@ -635,9 +632,9 @@
                                 // 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: "
+                                        "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());
@@ -1106,7 +1103,7 @@
             long end = Utils.ceilTime(startTimeMs, MAX_DUMMY_PROGRAM_DURATION);
             while (end < endTimeMs) {
                 programs.add(
-                        new ProgramImpl.Builder()
+                        new Program.Builder()
                                 .setStartTimeUtcMillis(start)
                                 .setEndTimeUtcMillis(end)
                                 .build());
@@ -1114,7 +1111,7 @@
                 end += MAX_DUMMY_PROGRAM_DURATION;
             }
             programs.add(
-                    new ProgramImpl.Builder()
+                    new Program.Builder()
                             .setStartTimeUtcMillis(start)
                             .setEndTimeUtcMillis(endTimeMs)
                             .build());
diff --git a/src/com/android/tv/TvApplication.java b/src/com/android/tv/TvApplication.java
index bc8226c..5f25a24 100644
--- a/src/com/android/tv/TvApplication.java
+++ b/src/com/android/tv/TvApplication.java
@@ -35,19 +35,20 @@
 import android.util.Log;
 import android.view.KeyEvent;
 import android.widget.Toast;
-
 import com.android.tv.common.BaseApplication;
 import com.android.tv.common.feature.CommonFeatures;
 import com.android.tv.common.recording.RecordingStorageStatusManager;
 import com.android.tv.common.ui.setup.animation.SetupAnimationHelper;
+import com.android.tv.common.util.Clock;
 import com.android.tv.common.util.Debug;
 import com.android.tv.common.util.SharedPreferencesUtils;
 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.data.epg.EpgReader;
+import com.android.tv.data.epg.EpgFetcherImpl;
 import com.android.tv.dvr.DvrDataManager;
+import com.android.tv.dvr.DvrDataManagerImpl;
 import com.android.tv.dvr.DvrManager;
 import com.android.tv.dvr.DvrScheduleManager;
 import com.android.tv.dvr.DvrStorageStatusManager;
@@ -55,9 +56,8 @@
 import com.android.tv.dvr.recorder.RecordingScheduler;
 import com.android.tv.dvr.ui.browse.DvrBrowseActivity;
 import com.android.tv.features.TvFeatures;
-import com.android.tv.perf.PerformanceMonitor;
-import com.android.tv.perf.StartupMeasure;
-import com.android.tv.perf.StartupMeasureFactory;
+import com.android.tv.perf.PerformanceMonitorManager;
+import com.android.tv.perf.PerformanceMonitorManagerFactory;
 import com.android.tv.recommendation.ChannelPreviewUpdater;
 import com.android.tv.recommendation.RecordedProgramPreviewUpdater;
 import com.android.tv.tunerinputcontroller.BuiltInTunerManager;
@@ -66,30 +66,27 @@
 import com.android.tv.util.SetupUtils;
 import com.android.tv.util.TvInputManagerHelper;
 import com.android.tv.util.Utils;
-
 import com.google.common.base.Optional;
-
 import dagger.Lazy;
-
-import com.android.tv.common.flags.CloudEpgFlags;
-import com.android.tv.common.flags.LegacyFlags;
-
 import java.util.List;
 import java.util.concurrent.Executor;
-
 import javax.inject.Inject;
 
 /**
- * TV application.
+ * Live TV application.
  *
  * <p>This includes all the Google specific hooks.
  */
 public abstract class TvApplication extends BaseApplication implements TvSingletons, Starter {
 
-    protected static final StartupMeasure STARTUP_MEASURE = StartupMeasureFactory.create();
+    protected static final PerformanceMonitorManager PERFORMANCE_MONITOR_MANAGER =
+            PerformanceMonitorManagerFactory.create();
     private static final String TAG = "TvApplication";
     private static final boolean DEBUG = false;
 
+    /** Namespace for LiveChannels configs. LiveChannels configs are kept in piper. */
+    public static final String CONFIGNS_P4 = "configns:p4";
+
     /**
      * Broadcast Action: The user has updated LC to a new version that supports tuner input. {@link
      * TunerInputController} will receive this intent to check the existence of tuner input when the
@@ -105,12 +102,12 @@
     private final MainActivityWrapper mMainActivityWrapper = new MainActivityWrapper();
 
     private SelectInputActivity mSelectInputActivity;
-    @Inject Lazy<ChannelDataManager> mChannelDataManager;
+    private ChannelDataManager mChannelDataManager;
     private volatile ProgramDataManager mProgramDataManager;
     private PreviewDataManager mPreviewDataManager;
     private DvrManager mDvrManager;
     private DvrScheduleManager mDvrScheduleManager;
-    @Inject Lazy<DvrDataManager> mDvrDataManager;
+    private DvrDataManager mDvrDataManager;
     private DvrWatchedPositionManager mDvrWatchedPositionManager;
     private RecordingScheduler mRecordingScheduler;
     private RecordingStorageStatusManager mDvrStorageStatusManager;
@@ -120,16 +117,11 @@
     private Boolean mRunningInMainProcess;
     @Inject Lazy<TvInputManagerHelper> mLazyTvInputManagerHelper;
     private boolean mStarted;
-    @Inject EpgFetcher mEpgFetcher;
+    private EpgFetcher mEpgFetcher;
 
     @Inject Optional<BuiltInTunerManager> mOptionalBuiltInTunerManager;
     @Inject SetupUtils mSetupUtils;
     @Inject @DbExecutor Executor mDbExecutor;
-    @Inject Lazy<EpgReader> mEpgReader;
-    @Inject BuildType mBuildType;
-    @Inject CloudEpgFlags mCloudEpgFlags;
-    @Inject LegacyFlags mLegacyFlags;
-    @Inject PerformanceMonitor mPerformanceMonitor;
 
     @Override
     public void onCreate() {
@@ -140,8 +132,6 @@
             throw new IllegalStateException(msg);
         }
         super.onCreate();
-        mPerformanceMonitor.startMemoryMonitor();
-        mPerformanceMonitor.startCrashMonitor();
         SharedPreferencesUtils.initialize(
                 this,
                 () -> {
@@ -156,15 +146,16 @@
             Log.w(TAG, "Unable to find package '" + getPackageName() + "'.", e);
             mVersionName = "";
         }
-        Log.i(TAG, "Starting TV app " + getVersionName());
+        Log.i(TAG, "Starting Live TV " + getVersionName());
 
         // 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.
+        mEpgFetcher = EpgFetcherImpl.create(this);
         SetupAnimationHelper.initialize(this);
         getTvInputManagerHelper();
 
-        Log.i(TAG, "Started TV app " + mVersionName);
+        Log.i(TAG, "Started Live TV " + mVersionName);
         Debug.getTimer(Debug.TAG_START_UP_TIMER).log("finish TvApplication.onCreate");
     }
 
@@ -219,10 +210,8 @@
             mEpgFetcher.startRoutineService();
             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                 ChannelPreviewUpdater.getInstance(this).startRoutineService();
-                if (CommonFeatures.DVR.isEnabled(this)) {
-                    RecordedProgramPreviewUpdater.getInstance(this)
-                            .updatePreviewDataForRecordedPrograms();
-                }
+                RecordedProgramPreviewUpdater.getInstance(this)
+                        .updatePreviewDataForRecordedPrograms();
             }
         }
         Debug.getTimer(Debug.TAG_START_UP_TIMER).log("finish TvApplication.start");
@@ -248,6 +237,11 @@
     }
 
     @Override
+    public EpgFetcher getEpgFetcher() {
+        return mEpgFetcher;
+    }
+
+    @Override
     public synchronized SetupUtils getSetupUtils() {
         return mSetupUtils;
     }
@@ -292,7 +286,16 @@
     /** Returns {@link ChannelDataManager}. */
     @Override
     public ChannelDataManager getChannelDataManager() {
-        return mChannelDataManager.get();
+        if (mChannelDataManager == null) {
+            mChannelDataManager = new ChannelDataManager(this, getTvInputManagerHelper());
+            mChannelDataManager.start();
+        }
+        return mChannelDataManager;
+    }
+
+    @Override
+    public boolean isChannelDataManagerLoadFinished() {
+        return mChannelDataManager != null && mChannelDataManager.isDbLoadFinished();
     }
 
     /** Returns {@link ProgramDataManager}. */
@@ -311,6 +314,11 @@
         return mProgramDataManager;
     }
 
+    @Override
+    public boolean isProgramDataManagerCurrentProgramsLoadFinished() {
+        return mProgramDataManager != null && mProgramDataManager.isCurrentProgramsLoadFinished();
+    }
+
     /** Returns {@link PreviewDataManager}. */
     @TargetApi(Build.VERSION_CODES.O)
     @Override
@@ -326,7 +334,12 @@
     @TargetApi(Build.VERSION_CODES.N)
     @Override
     public DvrDataManager getDvrDataManager() {
-        return mDvrDataManager.get();
+        if (mDvrDataManager == null) {
+            DvrDataManagerImpl dvrDataManager = new DvrDataManagerImpl(this, Clock.SYSTEM);
+            mDvrDataManager = dvrDataManager;
+            dvrDataManager.start();
+        }
+        return mDvrDataManager;
     }
 
     @Override
@@ -338,11 +351,6 @@
         return mDvrStorageStatusManager;
     }
 
-    @Override
-    public PerformanceMonitor getPerformanceMonitor() {
-        return mPerformanceMonitor;
-    }
-
     /** Returns the main activity information. */
     @Override
     public MainActivityWrapper getMainActivityWrapper() {
@@ -442,7 +450,7 @@
     }
 
     /**
-     * Returns the version name of the TV app.
+     * Returns the version name of the live channels.
      *
      * @see PackageInfo#versionName
      */
@@ -481,37 +489,6 @@
             Optional<String> optionalEmbeddedTunerInputId =
                     mOptionalBuiltInTunerManager.transform(
                             BuiltInTunerManager::getEmbeddedTunerInputId);
-            // If there is only play movies trailer input, we don't handle input count change.
-            final String playMoviesInputIdPrefix = "com.google.android.videos/";
-            int tunerInputCount = 0;
-            boolean hasPlayMoviesInput = false;
-            for (TvInputInfo input : inputs) {
-                if (calledByTunerServiceChanged
-                        && !tunerServiceEnabled
-                        && optionalEmbeddedTunerInputId.isPresent()
-                        && optionalEmbeddedTunerInputId.get().equals(input.getId())) {
-                    continue;
-                }
-                if (input.getType() == TvInputInfo.TYPE_TUNER) {
-                    if (DEBUG) Log.d(TAG, "Tuner input: " + input.getId());
-                    ++tunerInputCount;
-                    if (input.getId().startsWith(playMoviesInputIdPrefix)) {
-                        hasPlayMoviesInput = true;
-                    }
-                }
-            }
-            if (DEBUG) {
-                Log.d(
-                        TAG,
-                        "Input count: "
-                                + tunerInputCount
-                                + " hasPlayMoviesChannel: "
-                                + hasPlayMoviesInput);
-            }
-            if (tunerInputCount == 1 && hasPlayMoviesInput) {
-                if (DEBUG) Log.d(TAG, "There is only play movies input");
-                skipTunerInputCheck = true;
-            }
             // Enable the TvActivity only if there is at least one tuner type input.
             if (!skipTunerInputCheck) {
                 for (TvInputInfo input : inputs) {
@@ -538,24 +515,13 @@
         if (packageManager.getComponentEnabledSetting(name) != newState) {
             packageManager.setComponentEnabledSetting(
                     name, newState, dontKillApp ? PackageManager.DONT_KILL_APP : 0);
-            Log.i(TAG, (enable ? "Un-hide" : "Hide") + " TV app.");
+            Log.i(TAG, (enable ? "Un-hide" : "Hide") + " Live TV.");
         }
         mSetupUtils.onInputListUpdated(inputManager);
     }
 
     @Override
-    @DbExecutor
     public Executor getDbExecutor() {
         return mDbExecutor;
     }
-
-    @Override
-    public Lazy<EpgReader> providesEpgReader() {
-        return mEpgReader;
-    }
-
-    @Override
-    public BuildType getBuildType() {
-        return mBuildType;
-    }
 }
diff --git a/src/com/android/tv/TvSingletons.java b/src/com/android/tv/TvSingletons.java
index 9e4f462..20edf3d 100644
--- a/src/com/android/tv/TvSingletons.java
+++ b/src/com/android/tv/TvSingletons.java
@@ -17,15 +17,16 @@
 package com.android.tv;
 
 import android.content.Context;
-
 import com.android.tv.analytics.Analytics;
 import com.android.tv.analytics.Tracker;
 import com.android.tv.common.BaseApplication;
 import com.android.tv.common.BaseSingletons;
+import com.android.tv.common.experiments.ExperimentLoader;
 import com.android.tv.common.flags.has.HasUiFlags;
 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.data.epg.EpgReader;
 import com.android.tv.dvr.DvrDataManager;
 import com.android.tv.dvr.DvrManager;
@@ -36,27 +37,14 @@
 import com.android.tv.tunerinputcontroller.HasBuiltInTunerManager;
 import com.android.tv.util.SetupUtils;
 import com.android.tv.util.TvInputManagerHelper;
-
-import dagger.Lazy;
-
+import com.android.tv.util.account.AccountHelper;
 import com.android.tv.common.flags.BackendKnobsFlags;
-
 import java.util.concurrent.Executor;
+import javax.inject.Provider;
 
 /** Interface with getters for application scoped singletons. */
 public interface TvSingletons extends BaseSingletons, HasBuiltInTunerManager, HasUiFlags {
 
-    /*
-     * Do not add any new methods here.
-     *
-     * To move a getter to Injection.
-     *  1. Make a type injectable @Singleton.
-     *  2. Mark the getter here as deprecated.
-     *  3. Lazily inject the object in TvApplication.
-     *  4. Move easy usages of getters to injection instead.
-     *  5. Delete the method when all usages are migrated.
-     */
-
     /**
      * Returns the @{@link TvSingletons} using the application context.
      *
@@ -74,14 +62,24 @@
     @Deprecated
     ChannelDataManager getChannelDataManager();
 
+    /**
+     * Checks if the {@link ChannelDataManager} instance has been created and all the channels has
+     * been loaded.
+     */
+    boolean isChannelDataManagerLoadFinished();
+
     /** @deprecated use injection instead. */
     @Deprecated
     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();
 
-    /** @deprecated use injection instead. */
-    @Deprecated
     DvrDataManager getDvrDataManager();
 
     DvrScheduleManager getDvrScheduleManager();
@@ -90,8 +88,6 @@
 
     RecordingScheduler getRecordingScheduler();
 
-    /** @deprecated use injection instead. */
-    @Deprecated
     DvrWatchedPositionManager getDvrWatchedPositionManager();
 
     InputSessionManager getInputSessionManager();
@@ -100,22 +96,26 @@
 
     MainActivityWrapper getMainActivityWrapper();
 
+    AccountHelper getAccountHelper();
+
     boolean isRunningInMainProcess();
 
-    /** @deprecated use injection instead. */
-    @Deprecated
     PerformanceMonitor getPerformanceMonitor();
 
     /** @deprecated use injection instead. */
     @Deprecated
     TvInputManagerHelper getTvInputManagerHelper();
 
-    Lazy<EpgReader> providesEpgReader();
+    Provider<EpgReader> providesEpgReader();
+
+    EpgFetcher getEpgFetcher();
 
     /** @deprecated use injection instead. */
     @Deprecated
     SetupUtils getSetupUtils();
 
+    ExperimentLoader getExperimentLoader();
+
     /** @deprecated use injection instead. */
     @Deprecated
     Executor getDbExecutor();
diff --git a/src/com/android/tv/app/LiveTvApplication.java b/src/com/android/tv/app/LiveTvApplication.java
index 8090653..38e85e4 100644
--- a/src/com/android/tv/app/LiveTvApplication.java
+++ b/src/com/android/tv/app/LiveTvApplication.java
@@ -22,34 +22,50 @@
 import com.android.tv.analytics.StubAnalytics;
 import com.android.tv.analytics.Tracker;
 import com.android.tv.common.dagger.ApplicationModule;
+import com.android.tv.common.experiments.ExperimentLoader;
 import com.android.tv.common.flags.impl.DefaultBackendKnobsFlags;
 import com.android.tv.common.flags.impl.DefaultCloudEpgFlags;
+import com.android.tv.common.flags.impl.DefaultConcurrentDvrPlaybackFlags;
 import com.android.tv.common.flags.impl.DefaultUiFlags;
 import com.android.tv.common.singletons.HasSingletons;
+import com.android.tv.data.epg.EpgReader;
+import com.android.tv.data.epg.StubEpgReader;
 import com.android.tv.modules.TvSingletonsModule;
 import com.android.tv.perf.PerformanceMonitor;
+import com.android.tv.perf.PerformanceMonitorManagerFactory;
 import com.android.tv.tunerinputcontroller.BuiltInTunerManager;
-
+import com.android.tv.util.account.AccountHelper;
+import com.android.tv.util.account.AccountHelperImpl;
 import com.google.common.base.Optional;
-
 import dagger.android.AndroidInjector;
-
-import javax.inject.Inject;
+import javax.inject.Provider;
 
 /** The top level application for Live TV. */
 public class LiveTvApplication extends TvApplication implements HasSingletons<TvSingletons> {
 
     static {
-        STARTUP_MEASURE.onAppClassLoaded();
+        PERFORMANCE_MONITOR_MANAGER.getStartupMeasure().onAppClassLoaded();
     }
 
+    private final Provider<EpgReader> mEpgReaderProvider =
+            new Provider<EpgReader>() {
+
+                @Override
+                public EpgReader get() {
+                    return new StubEpgReader(LiveTvApplication.this);
+                }
+            };
+
     private final DefaultBackendKnobsFlags mBackendKnobsFlags = new DefaultBackendKnobsFlags();
     private final DefaultCloudEpgFlags mCloudEpgFlags = new DefaultCloudEpgFlags();
     private final DefaultUiFlags mUiFlags = new DefaultUiFlags();
-
+    private final DefaultConcurrentDvrPlaybackFlags mConcurrentDvrPlaybackFlags =
+            new DefaultConcurrentDvrPlaybackFlags();
+    private AccountHelper mAccountHelper;
     private Analytics mAnalytics;
     private Tracker mTracker;
-    @Inject PerformanceMonitor mPerformanceMonitor;
+    private ExperimentLoader mExperimentLoader;
+    private PerformanceMonitor mPerformanceMonitor;
 
     @Override
     protected AndroidInjector<LiveTvApplication> applicationInjector() {
@@ -62,15 +78,38 @@
     @Override
     public void onCreate() {
         super.onCreate();
-        STARTUP_MEASURE.onAppCreate(this);
+        PERFORMANCE_MONITOR_MANAGER.getStartupMeasure().onAppCreate(this);
+    }
+
+    /** Returns the {@link AccountHelperImpl}. */
+    @Override
+    public AccountHelper getAccountHelper() {
+        if (mAccountHelper == null) {
+            mAccountHelper = new AccountHelperImpl(getApplicationContext());
+        }
+        return mAccountHelper;
     }
 
     @Override
-    public PerformanceMonitor getPerformanceMonitor() {
+    public synchronized PerformanceMonitor getPerformanceMonitor() {
+        if (mPerformanceMonitor == null) {
+            mPerformanceMonitor = PerformanceMonitorManagerFactory.create().initialize(this);
+        }
         return mPerformanceMonitor;
     }
 
     @Override
+    public Provider<EpgReader> providesEpgReader() {
+        return mEpgReaderProvider;
+    }
+
+    @Override
+    public ExperimentLoader getExperimentLoader() {
+        mExperimentLoader = new ExperimentLoader();
+        return mExperimentLoader;
+    }
+
+    @Override
     public DefaultBackendKnobsFlags getBackendKnobs() {
         return mBackendKnobsFlags;
     }
@@ -109,6 +148,16 @@
     }
 
     @Override
+    public BuildType getBuildType() {
+        return BuildType.AOSP;
+    }
+
+    @Override
+    public DefaultConcurrentDvrPlaybackFlags getConcurrentDvrPlaybackFlags() {
+        return mConcurrentDvrPlaybackFlags;
+    }
+
+    @Override
     public TvSingletons singletons() {
         return this;
     }
diff --git a/src/com/android/tv/app/LiveTvApplicationComponent.java b/src/com/android/tv/app/LiveTvApplicationComponent.java
index 71ce1a8..3d3f049 100644
--- a/src/com/android/tv/app/LiveTvApplicationComponent.java
+++ b/src/com/android/tv/app/LiveTvApplicationComponent.java
@@ -15,7 +15,6 @@
  */
 package com.android.tv.app;
 
-import com.android.tv.search.LocalSearchProvider;
 import dagger.Component;
 import dagger.android.AndroidInjectionModule;
 import dagger.android.AndroidInjector;
@@ -23,10 +22,5 @@
 
 /** Dagger component for {@link LiveTvApplication}. */
 @Singleton
-@Component(
-    modules = {
-        AndroidInjectionModule.class,
-        LiveTvModule.class,
-        LocalSearchProvider.Module.class
-    })
+@Component(modules = {AndroidInjectionModule.class, LiveTvModule.class})
 public interface LiveTvApplicationComponent extends AndroidInjector<LiveTvApplication> {}
diff --git a/src/com/android/tv/app/LiveTvModule.java b/src/com/android/tv/app/LiveTvModule.java
index db631bc..a28749b 100644
--- a/src/com/android/tv/app/LiveTvModule.java
+++ b/src/com/android/tv/app/LiveTvModule.java
@@ -16,49 +16,18 @@
 package com.android.tv.app;
 
 import com.android.tv.common.flags.impl.DefaultFlagsModule;
-import com.android.tv.data.epg.EpgReader;
-import com.android.tv.data.epg.StubEpgReader;
 import com.android.tv.modules.TvApplicationModule;
-import com.android.tv.perf.PerformanceMonitor;
-import com.android.tv.perf.stub.StubPerformanceMonitor;
 import com.android.tv.tunerinputcontroller.BuiltInTunerManager;
-import com.android.tv.ui.sidepanel.DeveloperOptionFragment;
-import com.android.tv.util.account.AccountHelper;
-import com.android.tv.util.account.AccountHelperImpl;
 import com.google.common.base.Optional;
 import dagger.Module;
 import dagger.Provides;
-import javax.inject.Singleton;
 
 /** Dagger module for {@link LiveTvApplication}. */
 @Module(includes = {DefaultFlagsModule.class, TvApplicationModule.class})
 class LiveTvModule {
 
     @Provides
-    static AccountHelper providesAccountHelper(AccountHelperImpl impl) {
-        return impl;
-    }
-
-    @Provides
-    static Optional<DeveloperOptionFragment.AdditionalDeveloperItemsFactory>
-            providesAdditionalDeveloperItemsFactory() {
-        return Optional.absent();
-    }
-
-    @Provides
     Optional<BuiltInTunerManager> providesBuiltInTunerManager() {
         return Optional.absent();
     }
-
-    @Provides
-    @Singleton
-    PerformanceMonitor providesPerformanceMonitor() {
-        return new StubPerformanceMonitor();
-    }
-
-    @Provides
-    @Singleton
-    static EpgReader providesEpgReader(StubEpgReader impl) {
-        return impl;
-    }
 }
diff --git a/src/com/android/tv/data/BaseProgram.java b/src/com/android/tv/data/BaseProgram.java
new file mode 100644
index 0000000..9650fd1
--- /dev/null
+++ b/src/com/android/tv/data/BaseProgram.java
@@ -0,0 +1,208 @@
+/*
+ * 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.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 com.google.common.collect.ImmutableList;
+import java.util.Comparator;
+import java.util.Objects;
+
+/**
+ * Base class for {@link com.android.tv.data.Program} and {@link
+ * com.android.tv.dvr.data.RecordedProgram}.
+ */
+public abstract class BaseProgram {
+    /**
+     * Comparator used to compare {@link BaseProgram} according to its season and episodes number.
+     * If a program's season or episode number is null, it will be consider "smaller" than programs
+     * with season or episode numbers.
+     */
+    public static final Comparator<BaseProgram> EPISODE_COMPARATOR = new EpisodeComparator(false);
+
+    /**
+     * Comparator used to compare {@link BaseProgram} according to its season and episodes number
+     * with season numbers in a reversed order. If a program's season or episode number is null, it
+     * will be consider "smaller" than programs with season or episode numbers.
+     */
+    public static final Comparator<BaseProgram> SEASON_REVERSED_EPISODE_COMPARATOR =
+            new EpisodeComparator(true);
+
+    public static final String COLUMN_SERIES_ID = "series_id";
+
+    public static final String COLUMN_STATE = "state";
+
+    private static class EpisodeComparator implements Comparator<BaseProgram> {
+        private final boolean mReversedSeason;
+
+        EpisodeComparator(boolean reversedSeason) {
+            mReversedSeason = reversedSeason;
+        }
+
+        @Override
+        public int compare(BaseProgram lhs, BaseProgram rhs) {
+            if (lhs == rhs) {
+                return 0;
+            }
+            int seasonNumberCompare = numberCompare(lhs.getSeasonNumber(), rhs.getSeasonNumber());
+            if (seasonNumberCompare != 0) {
+                return mReversedSeason ? -seasonNumberCompare : seasonNumberCompare;
+            } else {
+                return numberCompare(lhs.getEpisodeNumber(), rhs.getEpisodeNumber());
+            }
+        }
+    }
+
+    /** Compares two strings represent season numbers or episode numbers of programs. */
+    public static int numberCompare(String s1, String s2) {
+        if (Objects.equals(s1, s2)) {
+            return 0;
+        } else if (s1 == null) {
+            return -1;
+        } else if (s2 == null) {
+            return 1;
+        } else if (s1.equals(s2)) {
+            return 0;
+        }
+        try {
+            return Integer.compare(Integer.parseInt(s1), Integer.parseInt(s2));
+        } catch (NumberFormatException e) {
+            return s1.compareTo(s2);
+        }
+    }
+
+    /** Returns ID of the program. */
+    public abstract long getId();
+
+    /** Returns the title of the program. */
+    public abstract String getTitle();
+
+    /** Returns the episode title. */
+    public abstract String getEpisodeTitle();
+
+    /** Returns the displayed title of the program episode. */
+    @Nullable
+    public String getEpisodeDisplayTitle(Context context) {
+        String episodeNumber = getEpisodeNumber();
+        String episodeTitle = getEpisodeTitle();
+        if (!TextUtils.isEmpty(episodeNumber)) {
+            episodeTitle = episodeTitle == null ? "" : episodeTitle;
+            String seasonNumber = getSeasonNumber();
+            if (TextUtils.isEmpty(seasonNumber) || TextUtils.equals(seasonNumber, "0")) {
+                // Do not show "S0: ".
+                return context.getResources()
+                        .getString(
+                                R.string.display_episode_title_format_no_season_number,
+                                episodeNumber,
+                                episodeTitle);
+            } else {
+                return context.getResources()
+                        .getString(
+                                R.string.display_episode_title_format,
+                                seasonNumber,
+                                episodeNumber,
+                                episodeTitle);
+            }
+        }
+        return episodeTitle;
+    }
+
+    /**
+     * Returns the content description of the program episode, suitable for being spoken by an
+     * accessibility service.
+     */
+    public String getEpisodeContentDescription(Context context) {
+        String episodeNumber = getEpisodeNumber();
+        String episodeTitle = getEpisodeTitle();
+        if (!TextUtils.isEmpty(episodeNumber)) {
+            episodeTitle = episodeTitle == null ? "" : episodeTitle;
+            String seasonNumber = getSeasonNumber();
+            if (TextUtils.isEmpty(seasonNumber) || TextUtils.equals(seasonNumber, "0")) {
+                // Do not list season if it is empty or 0
+                return context.getResources()
+                        .getString(
+                                R.string.content_description_episode_format_no_season_number,
+                                episodeNumber,
+                                episodeTitle);
+            } else {
+                return context.getResources()
+                        .getString(
+                                R.string.content_description_episode_format,
+                                seasonNumber,
+                                episodeNumber,
+                                episodeTitle);
+            }
+        }
+        return episodeTitle;
+    }
+
+    /** Returns the description of the program. */
+    public abstract String getDescription();
+
+    /** Returns the long description of the program. */
+    public abstract String getLongDescription();
+
+    /** Returns the start time of the program in Milliseconds. */
+    public abstract long getStartTimeUtcMillis();
+
+    /** Returns the end time of the program in Milliseconds. */
+    public abstract long getEndTimeUtcMillis();
+
+    /** Returns the duration of the program in Milliseconds. */
+    public abstract long getDurationMillis();
+
+    /** Returns the series ID. */
+    @Nullable
+    public abstract String getSeriesId();
+
+    /** Returns the season number. */
+    public abstract String getSeasonNumber();
+
+    /** Returns the episode number. */
+    public abstract String getEpisodeNumber();
+
+    /** Returns URI of the program's poster. */
+    public abstract String getPosterArtUri();
+
+    /** Returns URI of the program's thumbnail. */
+    public abstract String getThumbnailUri();
+
+    /** Returns the array of the ID's of the canonical genres. */
+    public abstract int[] getCanonicalGenreIds();
+
+    /** Returns the array of content ratings. */
+    public abstract ImmutableList<TvContentRating> getContentRatings();
+
+    /** Returns channel's ID of the program. */
+    public abstract long getChannelId();
+
+    /** Returns if the program is valid. */
+    public abstract 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) {
+        return packageName + "/" + title;
+    }
+}
diff --git a/src/com/android/tv/data/BaseProgramImpl.java b/src/com/android/tv/data/BaseProgramImpl.java
deleted file mode 100644
index 9c8d025..0000000
--- a/src/com/android/tv/data/BaseProgramImpl.java
+++ /dev/null
@@ -1,86 +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.data;
-
-import android.content.Context;
-import android.support.annotation.Nullable;
-import android.text.TextUtils;
-
-import com.android.tv.R;
-import com.android.tv.data.api.BaseProgram;
-
-/** Base class for {@link ProgramImpl} and {@link com.android.tv.dvr.data.RecordedProgram}. */
-public abstract class BaseProgramImpl implements BaseProgram {
-
-    @Override
-    @Nullable
-    public String getEpisodeDisplayTitle(Context context) {
-        String episodeNumber = getEpisodeNumber();
-        String episodeTitle = getEpisodeTitle();
-        if (!TextUtils.isEmpty(episodeNumber)) {
-            episodeTitle = episodeTitle == null ? "" : episodeTitle;
-            String seasonNumber = getSeasonNumber();
-            if (TextUtils.isEmpty(seasonNumber) || TextUtils.equals(seasonNumber, "0")) {
-                // Do not show "S0: ".
-                return context.getResources()
-                        .getString(
-                                R.string.display_episode_title_format_no_season_number,
-                                episodeNumber,
-                                episodeTitle);
-            } else {
-                return context.getResources()
-                        .getString(
-                                R.string.display_episode_title_format,
-                                seasonNumber,
-                                episodeNumber,
-                                episodeTitle);
-            }
-        }
-        return episodeTitle;
-    }
-
-    @Override
-    public String getEpisodeContentDescription(Context context) {
-        String episodeNumber = getEpisodeNumber();
-        String episodeTitle = getEpisodeTitle();
-        if (!TextUtils.isEmpty(episodeNumber)) {
-            episodeTitle = episodeTitle == null ? "" : episodeTitle;
-            String seasonNumber = getSeasonNumber();
-            if (TextUtils.isEmpty(seasonNumber) || TextUtils.equals(seasonNumber, "0")) {
-                // Do not list season if it is empty or 0
-                return context.getResources()
-                        .getString(
-                                R.string.content_description_episode_format_no_season_number,
-                                episodeNumber,
-                                episodeTitle);
-            } else {
-                return context.getResources()
-                        .getString(
-                                R.string.content_description_episode_format,
-                                seasonNumber,
-                                episodeNumber,
-                                episodeTitle);
-            }
-        }
-        return episodeTitle;
-    }
-
-    @Override
-    public boolean isEpisodic() {
-        return !TextUtils.isEmpty(getSeriesId());
-    }
-}
diff --git a/src/com/android/tv/data/ChannelDataManager.java b/src/com/android/tv/data/ChannelDataManager.java
index 67c3230..a5c786c 100644
--- a/src/com/android/tv/data/ChannelDataManager.java
+++ b/src/com/android/tv/data/ChannelDataManager.java
@@ -37,18 +37,15 @@
 import android.util.ArraySet;
 import android.util.Log;
 import android.util.MutableInt;
+import com.android.tv.TvSingletons;
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.common.WeakHandler;
-import com.android.tv.common.dagger.annotations.ApplicationContext;
 import com.android.tv.common.util.PermissionUtils;
 import com.android.tv.common.util.SharedPreferencesUtils;
 import com.android.tv.data.api.Channel;
 import com.android.tv.util.AsyncDbTask;
-import com.android.tv.util.AsyncDbTask.DbExecutor;
 import com.android.tv.util.TvInputManagerHelper;
 import com.android.tv.util.Utils;
-import com.google.auto.factory.AutoFactory;
-import com.google.auto.factory.Provided;
 import java.io.FileNotFoundException;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -59,7 +56,6 @@
 import java.util.Set;
 import java.util.concurrent.CopyOnWriteArraySet;
 import java.util.concurrent.Executor;
-import javax.inject.Singleton;
 
 /**
  * The class to manage channel data. Basic features: reading channel list and each channel's current
@@ -68,8 +64,6 @@
  * methods are called in only the main thread.
  */
 @AnyThread
-@AutoFactory
-@Singleton
 public class ChannelDataManager {
     private static final String TAG = "ChannelDataManager";
     private static final boolean DEBUG = false;
@@ -149,11 +143,21 @@
             };
 
     @MainThread
-    public ChannelDataManager(
-            @Provided @ApplicationContext Context context,
-            @Provided TvInputManagerHelper inputManager,
-            @Provided @DbExecutor Executor executor,
-            @Provided ContentResolver contentResolver) {
+    public ChannelDataManager(Context context, TvInputManagerHelper inputManager) {
+        this(
+                context,
+                inputManager,
+                TvSingletons.getSingletons(context).getDbExecutor(),
+                context.getContentResolver());
+    }
+
+    @MainThread
+    @VisibleForTesting
+    ChannelDataManager(
+            Context context,
+            TvInputManagerHelper inputManager,
+            Executor executor,
+            ContentResolver contentResolver) {
         mContext = context;
         mInputManager = inputManager;
         mDbExecutor = executor;
@@ -725,7 +729,7 @@
     /**
      * Updates a column {@code columnName} of DB table {@code uri} with the value {@code
      * columnValue}. The selective rows in the ID list {@code ids} will be updated. The DB
-     * operations will run on @{@link DbExecutor}.
+     * operations will run on {@link TvSingletons#getDbExecutor()}.
      */
     private void updateOneColumnValue(
             final String columnName, final int columnValue, final List<Long> ids) {
diff --git a/src/com/android/tv/data/InternalDataUtils.java b/src/com/android/tv/data/InternalDataUtils.java
index b17ed09..4c30d39 100644
--- a/src/com/android/tv/data/InternalDataUtils.java
+++ b/src/com/android/tv/data/InternalDataUtils.java
@@ -19,11 +19,8 @@
 import android.support.annotation.Nullable;
 import android.text.TextUtils;
 import android.util.Log;
-
-import com.android.tv.data.api.Program;
-import com.android.tv.data.api.Program.CriticScore;
+import com.android.tv.data.Program.CriticScore;
 import com.android.tv.dvr.data.RecordedProgram;
-
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -52,7 +49,7 @@
      * @param bytes the bytes to be deserialized
      * @param builder the builder for the Program class
      */
-    public static void deserializeInternalProviderData(byte[] bytes, ProgramImpl.Builder builder) {
+    public static void deserializeInternalProviderData(byte[] bytes, Program.Builder builder) {
         if (bytes == null || bytes.length == 0) {
             return;
         }
diff --git a/src/com/android/tv/data/OnCurrentProgramUpdatedListener.java b/src/com/android/tv/data/OnCurrentProgramUpdatedListener.java
index 2332cda..edb3355 100644
--- a/src/com/android/tv/data/OnCurrentProgramUpdatedListener.java
+++ b/src/com/android/tv/data/OnCurrentProgramUpdatedListener.java
@@ -16,8 +16,6 @@
 
 package com.android.tv.data;
 
-import com.android.tv.data.api.Program;
-
 public interface OnCurrentProgramUpdatedListener {
     /** Called when the current program is updated. */
     void onCurrentProgramUpdated(long channelId, Program program);
diff --git a/src/com/android/tv/data/PreviewDataManager.java b/src/com/android/tv/data/PreviewDataManager.java
index dbe6028..8616aee 100644
--- a/src/com/android/tv/data/PreviewDataManager.java
+++ b/src/com/android/tv/data/PreviewDataManager.java
@@ -32,14 +32,10 @@
 import android.support.annotation.MainThread;
 import android.util.Log;
 import android.util.Pair;
-
 import androidx.tvprovider.media.tv.ChannelLogoUtils;
 import androidx.tvprovider.media.tv.PreviewProgram;
-
 import com.android.tv.R;
 import com.android.tv.common.util.PermissionUtils;
-import com.android.tv.util.images.ImageLoader;
-
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.HashMap;
@@ -222,7 +218,7 @@
                 Uri previewChannelsUri =
                         PreviewDataUtils.addQueryParamToUri(
                                 TvContract.Channels.CONTENT_URI,
-                                Pair.create(PARAM_PREVIEW, String.valueOf(true)));
+                                new Pair<>(PARAM_PREVIEW, String.valueOf(true)));
                 String packageName = mContext.getPackageName();
                 if (PermissionUtils.hasAccessAllEpg(mContext)) {
                     try (Cursor cursor =
@@ -432,14 +428,10 @@
                     continue;
                 }
                 try {
-                    int aspectRatio =
-                            ImageLoader.getAspectRatioFromPosterArtUri(
-                                    mContext, program.getPosterArtUri().toString());
                     Uri programUri =
                             mContentResolver.insert(
                                     TvContract.PreviewPrograms.CONTENT_URI,
-                                    PreviewDataUtils.createPreviewProgramFromContent(
-                                                    program, aspectRatio)
+                                    PreviewDataUtils.createPreviewProgramFromContent(program)
                                             .toContentValues());
                     if (programUri != null) {
                         long previewProgramId = ContentUris.parseId(programUri);
@@ -600,14 +592,13 @@
 
         /** Creates a preview program. */
         public static PreviewProgram createPreviewProgramFromContent(
-                PreviewProgramContent program, int aspectRatio) {
+                PreviewProgramContent program) {
             PreviewProgram.Builder builder = new PreviewProgram.Builder();
             builder.setChannelId(program.getPreviewChannelId())
                     .setType(program.getType())
                     .setLive(program.getLive())
                     .setTitle(program.getTitle())
                     .setDescription(program.getDescription())
-                    .setPosterArtAspectRatio(aspectRatio)
                     .setPosterArtUri(program.getPosterArtUri())
                     .setIntentUri(program.getIntentUri())
                     .setPreviewVideoUri(program.getPreviewVideoUri())
diff --git a/src/com/android/tv/data/PreviewProgramContent.java b/src/com/android/tv/data/PreviewProgramContent.java
index 4ee5710..8d4b88c 100644
--- a/src/com/android/tv/data/PreviewProgramContent.java
+++ b/src/com/android/tv/data/PreviewProgramContent.java
@@ -21,14 +21,10 @@
 import android.support.annotation.VisibleForTesting;
 import android.text.TextUtils;
 import android.util.Pair;
-
 import androidx.tvprovider.media.tv.TvContractCompat;
-
 import com.android.tv.TvSingletons;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
 import com.android.tv.dvr.data.RecordedProgram;
-
 import java.util.Objects;
 
 /** A class to store the content of preview programs. */
@@ -45,7 +41,7 @@
     private Uri mIntentUri;
     private Uri mPreviewVideoUri;
 
-    /** Create preview program content from {@link ProgramImpl} */
+    /** Create preview program content from {@link Program} */
     public static PreviewProgramContent createFromProgram(
             Context context, long previewChannelId, Program program) {
         Channel channel =
@@ -83,7 +79,7 @@
                 .setIntentUri(channel.getUri())
                 .setPreviewVideoUri(
                         PreviewDataManager.PreviewDataUtils.addQueryParamToUri(
-                                channel.getUri(), Pair.create(PARAM_INPUT, channel.getInputId())))
+                                channel.getUri(), new Pair<>(PARAM_INPUT, channel.getInputId())))
                 .build();
     }
 
@@ -103,7 +99,7 @@
                 .setPreviewVideoUri(
                         PreviewDataManager.PreviewDataUtils.addQueryParamToUri(
                                 recordedProgramUri,
-                                Pair.create(PARAM_INPUT, recordedProgram.getInputId())))
+                                new Pair<>(PARAM_INPUT, recordedProgram.getInputId())))
                 .build();
     }
 
diff --git a/src/com/android/tv/data/ProgramImpl.java b/src/com/android/tv/data/Program.java
similarity index 86%
rename from src/com/android/tv/data/ProgramImpl.java
rename to src/com/android/tv/data/Program.java
index 5097e2d..b688927 100644
--- a/src/com/android/tv/data/ProgramImpl.java
+++ b/src/com/android/tv/data/Program.java
@@ -32,26 +32,24 @@
 import android.support.annotation.VisibleForTesting;
 import android.support.annotation.WorkerThread;
 import android.text.TextUtils;
-
+import android.util.Log;
+import com.android.tv.common.BuildConfig;
 import com.android.tv.common.TvContentRatingCache;
 import com.android.tv.common.util.CollectionUtils;
 import com.android.tv.common.util.CommonUtils;
-import com.android.tv.data.api.BaseProgram;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
 import com.android.tv.util.TvProviderUtils;
 import com.android.tv.util.Utils;
 import com.android.tv.util.images.ImageLoader;
-
 import com.google.common.collect.ImmutableList;
-
+import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
 
 /** A convenience class to create and insert program information entries into the database. */
-public final class ProgramImpl extends BaseProgramImpl implements Parcelable, Program {
+public final class Program extends BaseProgram implements Comparable<Program>, Parcelable {
     private static final boolean DEBUG = false;
     private static final boolean DEBUG_DUMP_DESCRIPTION = false;
     private static final String TAG = "Program";
@@ -181,8 +179,8 @@
         return builder.build();
     }
 
-    public static ProgramImpl fromParcel(Parcel in) {
-        ProgramImpl program = new ProgramImpl();
+    public static Program fromParcel(Parcel in) {
+        Program program = new Program();
         program.mId = in.readLong();
         program.mPackageName = in.readString();
         program.mChannelId = in.readLong();
@@ -221,7 +219,7 @@
             new Parcelable.Creator<Program>() {
                 @Override
                 public Program createFromParcel(Parcel in) {
-                    return ProgramImpl.fromParcel(in);
+                    return Program.fromParcel(in);
                 }
 
                 @Override
@@ -253,21 +251,19 @@
     private ImmutableList<TvContentRating> mContentRatings;
     private boolean mRecordingProhibited;
 
-    private ProgramImpl() {
+    private Program() {
         // Do nothing.
     }
 
-    @Override
     public long getId() {
         return mId;
     }
 
-    @Override
+    /** Returns the package name of this program. */
     public String getPackageName() {
         return mPackageName;
     }
 
-    @Override
     public long getChannelId() {
         return mChannelId;
     }
@@ -278,6 +274,11 @@
         return mChannelId >= 0;
     }
 
+    /** Returns {@code true} if the program is valid and {@code false} otherwise. */
+    public static boolean isProgramValid(Program program) {
+        return program != null && program.isValid();
+    }
+
     @Override
     public String getTitle() {
         return mTitle;
@@ -301,11 +302,6 @@
     }
 
     @Override
-    public String getSeasonTitle() {
-        return mSeasonTitle;
-    }
-
-    @Override
     public String getEpisodeNumber() {
         return mEpisodeNumber;
     }
@@ -320,7 +316,6 @@
         return mEndTimeUtcMillis;
     }
 
-    @Override
     public String getDurationString(Context context) {
         // TODO(b/71717446): expire the calculated string
         if (mDurationString == null) {
@@ -346,17 +341,15 @@
         return mLongDescription;
     }
 
-    @Override
     public int getVideoWidth() {
         return mVideoWidth;
     }
 
-    @Override
     public int getVideoHeight() {
         return mVideoHeight;
     }
 
-    @Override
+    /** Returns the list of Critic Scores for this program */
     @Nullable
     public List<CriticScore> getCriticScores() {
         return mCriticScores;
@@ -378,12 +371,12 @@
         return mThumbnailUri;
     }
 
-    @Override
+    /** Returns {@code true} if the recording of this program is prohibited. */
     public boolean isRecordingProhibited() {
         return mRecordingProhibited;
     }
 
-    @Override
+    /** Returns array of canonical genres for this program. This is expected to be called rarely. */
     @Nullable
     public String[] getCanonicalGenres() {
         if (mCanonicalGenreIds == null) {
@@ -402,7 +395,7 @@
         return mCanonicalGenreIds;
     }
 
-    @Override
+    /** Returns if this program has the genre. */
     public boolean hasGenre(int genreId) {
         if (genreId == GenreItems.ID_ALL_CHANNELS) {
             return true;
@@ -443,11 +436,11 @@
 
     @Override
     public boolean equals(Object other) {
-        if (!(other instanceof ProgramImpl)) {
+        if (!(other instanceof Program)) {
             return false;
         }
         // Compare all the properties because program ID can be invalid for the dummy programs.
-        ProgramImpl program = (ProgramImpl) other;
+        Program program = (Program) other;
         return Objects.equals(mPackageName, program.mPackageName)
                 && mChannelId == program.mChannelId
                 && mStartTimeUtcMillis == program.mStartTimeUtcMillis
@@ -471,7 +464,7 @@
 
     @Override
     public int compareTo(@NonNull Program other) {
-        return Long.compare(mStartTimeUtcMillis, other.getStartTimeUtcMillis());
+        return Long.compare(mStartTimeUtcMillis, other.mStartTimeUtcMillis);
     }
 
     @Override
@@ -523,7 +516,7 @@
     }
 
     /**
-     * Translates a {@link ProgramImpl} to {@link ContentValues} that are ready to be written into
+     * Translates a {@link Program} to {@link ContentValues} that are ready to be written into
      * Database.
      */
     @SuppressLint("InlinedApi")
@@ -602,37 +595,37 @@
             return;
         }
 
-        mId = other.getId();
-        mPackageName = other.getPackageName();
-        mChannelId = other.getChannelId();
-        mTitle = other.getTitle();
-        mSeriesId = other.getSeriesId();
-        mEpisodeTitle = other.getEpisodeTitle();
-        mSeasonNumber = other.getSeasonNumber();
-        mSeasonTitle = other.getSeasonTitle();
-        mEpisodeNumber = other.getEpisodeNumber();
-        mStartTimeUtcMillis = other.getStartTimeUtcMillis();
-        mEndTimeUtcMillis = other.getEndTimeUtcMillis();
+        mId = other.mId;
+        mPackageName = other.mPackageName;
+        mChannelId = other.mChannelId;
+        mTitle = other.mTitle;
+        mSeriesId = other.mSeriesId;
+        mEpisodeTitle = other.mEpisodeTitle;
+        mSeasonNumber = other.mSeasonNumber;
+        mSeasonTitle = other.mSeasonTitle;
+        mEpisodeNumber = other.mEpisodeNumber;
+        mStartTimeUtcMillis = other.mStartTimeUtcMillis;
+        mEndTimeUtcMillis = other.mEndTimeUtcMillis;
         mDurationString = null; // Recreate Duration when needed.
-        mDescription = other.getDescription();
-        mLongDescription = other.getLongDescription();
-        mVideoWidth = other.getVideoWidth();
-        mVideoHeight = other.getVideoHeight();
-        mCriticScores = other.getCriticScores();
-        mPosterArtUri = other.getPosterArtUri();
-        mThumbnailUri = other.getThumbnailUri();
-        mCanonicalGenreIds = other.getCanonicalGenreIds();
-        mContentRatings = other.getContentRatings();
-        mRecordingProhibited = other.isRecordingProhibited();
+        mDescription = other.mDescription;
+        mLongDescription = other.mLongDescription;
+        mVideoWidth = other.mVideoWidth;
+        mVideoHeight = other.mVideoHeight;
+        mCriticScores = other.mCriticScores;
+        mPosterArtUri = other.mPosterArtUri;
+        mThumbnailUri = other.mThumbnailUri;
+        mCanonicalGenreIds = other.mCanonicalGenreIds;
+        mContentRatings = other.mContentRatings;
+        mRecordingProhibited = other.mRecordingProhibited;
     }
 
     /** A Builder for the Program class */
     public static final class Builder {
-        private final ProgramImpl mProgram;
+        private final Program mProgram;
 
         /** Creates a Builder for this Program class */
         public Builder() {
-            mProgram = new ProgramImpl();
+            mProgram = new Program();
             // Fill initial data.
             mProgram.mPackageName = null;
             mProgram.mChannelId = Channel.INVALID_ID;
@@ -657,7 +650,7 @@
          */
         @VisibleForTesting
         public Builder(Program other) {
-            mProgram = new ProgramImpl();
+            mProgram = new Program();
             mProgram.copyFrom(other);
         }
 
@@ -913,7 +906,7 @@
          *
          * @return the Program object constructed
          */
-        public ProgramImpl build() {
+        public Program build() {
             // Generate the series ID for the episodic program of other TV input.
             if (TextUtils.isEmpty(mProgram.mTitle)) {
                 // If title is null, series cannot be generated for this program.
@@ -923,13 +916,17 @@
                 // If series ID is not set, generate it for the episodic program of other TV input.
                 setSeriesId(BaseProgram.generateSeriesId(mProgram.mPackageName, mProgram.mTitle));
             }
-            ProgramImpl program = new ProgramImpl();
+            Program program = new Program();
             program.copyFrom(mProgram);
             return program;
         }
     }
 
-    @Override
+    /**
+     * Prefetches the program poster art.
+     *
+     * <p>
+     */
     public void prefetchPosterArt(Context context, int posterArtWidth, int posterArtHeight) {
         if (mPosterArtUri == null) {
             return;
@@ -937,13 +934,20 @@
         ImageLoader.prefetchBitmap(context, mPosterArtUri, posterArtWidth, posterArtHeight);
     }
 
-    @Override
+    /**
+     * 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 boolean loadPosterArt(
             Context context,
             int posterArtWidth,
             int posterArtHeight,
-            ImageLoader.ImageLoaderCallback<?> callback) {
+            ImageLoader.ImageLoaderCallback callback) {
         if (mPosterArtUri == null) {
             return false;
         }
@@ -951,9 +955,24 @@
                 context, mPosterArtUri, posterArtWidth, posterArtHeight, callback);
     }
 
-    @Override
-    public Parcelable toParcelable() {
-        return this;
+    public static boolean isDuplicate(Program p1, Program p2) {
+        if (p1 == null || p2 == null) {
+            return false;
+        }
+        boolean isDuplicate =
+                p1.getChannelId() == p2.getChannelId()
+                        && p1.getStartTimeUtcMillis() == p2.getStartTimeUtcMillis()
+                        && p1.getEndTimeUtcMillis() == p2.getEndTimeUtcMillis();
+        if (DEBUG && BuildConfig.ENG && isDuplicate) {
+            Log.w(
+                    TAG,
+                    "Duplicate programs detected! - \""
+                            + p1.getTitle()
+                            + "\" and \""
+                            + p2.getTitle()
+                            + "\"");
+        }
+        return isDuplicate;
     }
 
     @Override
@@ -990,4 +1009,54 @@
         }
         out.writeByte((byte) (mRecordingProhibited ? 1 : 0));
     }
+
+    /** Holds one type of critic score and its source. */
+    public static final class CriticScore implements Serializable, Parcelable {
+        /** The source of the rating. */
+        public final String source;
+        /** The score. */
+        public final String score;
+        /** The url of the logo image */
+        public final String logoUrl;
+
+        public static final Parcelable.Creator<CriticScore> CREATOR =
+                new Parcelable.Creator<CriticScore>() {
+                    @Override
+                    public CriticScore createFromParcel(Parcel in) {
+                        String source = in.readString();
+                        String score = in.readString();
+                        String logoUri = in.readString();
+                        return new CriticScore(source, score, logoUri);
+                    }
+
+                    @Override
+                    public CriticScore[] newArray(int size) {
+                        return new CriticScore[size];
+                    }
+                };
+
+        /**
+         * Constructor for this class.
+         *
+         * @param source the source of the rating
+         * @param score the score
+         */
+        public CriticScore(String source, String score, String logoUrl) {
+            this.source = source;
+            this.score = score;
+            this.logoUrl = logoUrl;
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel out, int i) {
+            out.writeString(source);
+            out.writeString(score);
+            out.writeString(logoUrl);
+        }
+    }
 }
diff --git a/src/com/android/tv/data/ProgramDataManager.java b/src/com/android/tv/data/ProgramDataManager.java
index a866c78..2f20c89 100644
--- a/src/com/android/tv/data/ProgramDataManager.java
+++ b/src/com/android/tv/data/ProgramDataManager.java
@@ -33,24 +33,19 @@
 import android.util.Log;
 import android.util.LongSparseArray;
 import android.util.LruCache;
-
 import com.android.tv.TvSingletons;
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.common.memory.MemoryManageable;
 import com.android.tv.common.util.Clock;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
 import com.android.tv.perf.EventNames;
 import com.android.tv.perf.PerformanceMonitor;
 import com.android.tv.perf.TimerEvent;
 import com.android.tv.util.AsyncDbTask;
 import com.android.tv.util.MultiLongSparseArray;
-import com.android.tv.util.TvInputManagerHelper;
 import com.android.tv.util.TvProviderUtils;
 import com.android.tv.util.Utils;
-
 import com.android.tv.common.flags.BackendKnobsFlags;
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -80,11 +75,6 @@
     private static final long CURRENT_PROGRAM_UPDATE_WAIT_MS = TimeUnit.SECONDS.toMillis(5);
     @VisibleForTesting static final long PROGRAM_GUIDE_SNAP_TIME_MS = TimeUnit.MINUTES.toMillis(30);
 
-    // Default fetch hours
-    private static final long FETCH_HOURS_MS = TimeUnit.HOURS.toMillis(24);
-    // Load data earlier for smooth scrolling.
-    private static final long BUFFER_HOURS_MS = TimeUnit.HOURS.toMillis(6);
-
     // TODO: Use TvContract constants, once they become public.
     private static final String PARAM_START_TIME = "start_time";
     private static final String PARAM_END_TIME = "end_time";
@@ -96,20 +86,10 @@
                     + Programs.COLUMN_CHANNEL_ID
                     + ", "
                     + Programs.COLUMN_END_TIME_UTC_MILLIS;
-    private static final String SORT_BY_CHANNEL_ID =
-            Programs.COLUMN_CHANNEL_ID
-                    + ", "
-                    + Programs.COLUMN_START_TIME_UTC_MILLIS
-                    + " DESC, "
-                    + Programs.COLUMN_END_TIME_UTC_MILLIS
-                    + " ASC, "
-                    + Programs._ID
-                    + " DESC";
 
     private static final int MSG_UPDATE_CURRENT_PROGRAMS = 1000;
     private static final int MSG_UPDATE_ONE_CURRENT_PROGRAM = 1001;
     private static final int MSG_UPDATE_PREFETCH_PROGRAM = 1002;
-    private static final int MSG_UPDATE_CONTENT_RATINGS = 1003;
 
     private final Context mContext;
     private final Clock mClock;
@@ -118,7 +98,6 @@
     private final BackendKnobsFlags mBackendKnobsFlags;
     private final PerformanceMonitor mPerformanceMonitor;
     private final ChannelDataManager mChannelDataManager;
-    private final TvInputManagerHelper mTvInputManagerHelper;
     private boolean mStarted;
     // Updated only on the main thread.
     private volatile boolean mCurrentProgramsLoadFinished;
@@ -146,11 +125,6 @@
 
     private boolean mPauseProgramUpdate = false;
     private final LruCache<Long, Program> mZeroLengthProgramCache = new LruCache<>(10);
-    // Current tuned channel.
-    private long mTunedChannelId;
-    // Hours of data to be fetched, it is updated during horizontal scroll.
-    // Note that it should never exceed programGuideMaxHours.
-    private long mMaxFetchHoursMs = FETCH_HOURS_MS;
 
     @MainThread
     public ProgramDataManager(Context context) {
@@ -162,8 +136,7 @@
                 Looper.myLooper(),
                 TvSingletons.getSingletons(context).getBackendKnobs(),
                 TvSingletons.getSingletons(context).getPerformanceMonitor(),
-                TvSingletons.getSingletons(context).getChannelDataManager(),
-                TvSingletons.getSingletons(context).getTvInputManagerHelper());
+                TvSingletons.getSingletons(context).getChannelDataManager());
     }
 
     @VisibleForTesting
@@ -175,8 +148,7 @@
             Looper looper,
             BackendKnobsFlags backendKnobsFlags,
             PerformanceMonitor performanceMonitor,
-            ChannelDataManager channelDataManager,
-            TvInputManagerHelper tvInputManagerHelper) {
+            ChannelDataManager channelDataManager) {
         mContext = context;
         mDbExecutor = executor;
         mClock = time;
@@ -185,7 +157,6 @@
         mBackendKnobsFlags = backendKnobsFlags;
         mPerformanceMonitor = performanceMonitor;
         mChannelDataManager = channelDataManager;
-        mTvInputManagerHelper = tvInputManagerHelper;
         mProgramObserver =
                 new ContentObserver(mHandler) {
                     @Override
@@ -234,7 +205,6 @@
         // Should be called directly instead of posting MSG_UPDATE_CURRENT_PROGRAMS message
         // to the handler. If not, another DB task can be executed before loading current programs.
         handleUpdateCurrentPrograms();
-        mHandler.sendEmptyMessage(MSG_UPDATE_CONTENT_RATINGS);
         if (mPrefetchEnabled) {
             mHandler.sendEmptyMessage(MSG_UPDATE_PREFETCH_PROGRAM);
         }
@@ -289,69 +259,17 @@
         }
     }
 
-    /**
-     * Prefetch program data if needed.
-     *
-     * @param channelId ID of the channel to prefetch
-     * @param selectedProgramIndex index of selected program.
-     */
-    public void prefetchChannel(long channelId, int selectedProgramIndex) {
-        long startTimeMs =
-                Utils.floorTime(
-                        mClock.currentTimeMillis() - PROGRAM_GUIDE_SNAP_TIME_MS,
-                        PROGRAM_GUIDE_SNAP_TIME_MS);
-        long programGuideMaxHoursMs =
-                TimeUnit.HOURS.toMillis(mBackendKnobsFlags.programGuideMaxHours());
-        long endTimeMs = 0;
-        if (mMaxFetchHoursMs < programGuideMaxHoursMs
-                && isHorizontalLoadNeeded(startTimeMs, channelId, selectedProgramIndex)) {
-            // Horizontal scrolling needs to load data of further days.
-            mMaxFetchHoursMs = Math.min(programGuideMaxHoursMs, mMaxFetchHoursMs + FETCH_HOURS_MS);
-            mCompleteInfoChannelIds.clear();
-        }
-        // Load max hours complete data for first channel.
-        if (mCompleteInfoChannelIds.isEmpty()) {
-            endTimeMs = startTimeMs + programGuideMaxHoursMs;
-        } else if (!mCompleteInfoChannelIds.contains(channelId)) {
-            endTimeMs = startTimeMs + mMaxFetchHoursMs;
-        }
-        if (endTimeMs > 0) {
-            mCompleteInfoChannelIds.add(channelId);
+    public void prefetchChannel(long channelId) {
+        if (mCompleteInfoChannelIds.add(channelId)) {
+            long startTimeMs =
+                    Utils.floorTime(
+                            mClock.currentTimeMillis() - PROGRAM_GUIDE_SNAP_TIME_MS,
+                            PROGRAM_GUIDE_SNAP_TIME_MS);
+            long endTimeMs = startTimeMs + TimeUnit.HOURS.toMillis(getFetchDuration());
             new SingleChannelPrefetchTask(channelId, startTimeMs, endTimeMs).executeOnDbThread();
         }
     }
 
-    public void prefetchChannel(long channelId) {
-        prefetchChannel(channelId, 0);
-    }
-
-    /**
-     * Check if enough data is present for horizontal scroll, otherwise prefetch programs.
-     *
-     * <p>If end time of current program is past {@code BUFFER_HOURS_MS} less than the fetched time
-     * we need to prefetch proceeding programs.
-     *
-     * @param startTimeMs Fetch start time, it is used to get fetch end time.
-     * @param channelId
-     * @param selectedProgramIndex
-     * @return {@code true} If data load is needed, else {@code false}.
-     */
-    private boolean isHorizontalLoadNeeded(
-            long startTimeMs, long channelId, int selectedProgramIndex) {
-        if (mChannelIdProgramCache.containsKey(channelId)) {
-            ArrayList<Program> programs = mChannelIdProgramCache.get(channelId);
-            long marginEndTime = startTimeMs + mMaxFetchHoursMs - BUFFER_HOURS_MS;
-            return programs.size() > selectedProgramIndex &&
-                    programs.get(selectedProgramIndex).getEndTimeUtcMillis() > marginEndTime;
-        }
-        return false;
-    }
-
-    public void onChannelTuned(long channelId) {
-        mTunedChannelId = channelId;
-        prefetchChannel(channelId);
-    }
-
     /** A Callback interface to receive notification on program data retrieval from DB. */
     public interface Callback {
         /**
@@ -362,10 +280,12 @@
         void onProgramUpdated();
 
         /**
-         * Called when we update program data during scrolling. Data is loaded from DB on request
-         * basis. It loads data based on horizontal scrolling as well.
+         * Called when we update complete program data of specific channel during scrolling. Data is
+         * loaded from DB on request basis.
+         *
+         * @param channelId
          */
-        void onChannelUpdated();
+        void onSingleChannelUpdated(long channelId);
     }
 
     /** Adds the {@link Callback}. */
@@ -392,7 +312,7 @@
         } else {
             mPrefetchEnabled = false;
             cancelPrefetchTask();
-            clearChannelInfoMap();
+            mChannelIdProgramCache.clear();
             mHandler.removeMessages(MSG_UPDATE_PREFETCH_PROGRAM);
         }
     }
@@ -619,7 +539,10 @@
                 }
                 programMap.clear();
 
-                String[] projection = ProgramImpl.PARTIAL_PROJECTION;
+                String[] projection =
+                        mBackendKnobsFlags.enablePartialProgramFetch()
+                                ? Program.PARTIAL_PROJECTION
+                                : Program.PROJECTION;
                 if (TvProviderUtils.checkSeriesIdColumn(mContext, Programs.CONTENT_URI)) {
                     if (Utils.isProgramsUri(uri)) {
                         projection =
@@ -639,7 +562,10 @@
                             }
                             return null;
                         }
-                        Program program = ProgramImpl.fromCursorPartialProjection(c);
+                        Program program =
+                                mBackendKnobsFlags.enablePartialProgramFetch()
+                                        ? Program.fromCursorPartialProjection(c)
+                                        : Program.fromCursor(c);
                         if (Program.isDuplicate(program, lastReadProgram)) {
                             duplicateCount++;
                             continue;
@@ -649,14 +575,15 @@
                         ArrayList<Program> programs = programMap.get(program.getChannelId());
                         if (programs == null) {
                             programs = new ArrayList<>();
-                            // To skip already loaded complete data.
-                            Program currentProgramInfo =
-                                    mChannelIdCurrentProgramMap.get(program.getChannelId());
-                            if (currentProgramInfo != null
-                                    && Program.isDuplicate(program, currentProgramInfo)) {
-                                program = currentProgramInfo;
+                            if (mBackendKnobsFlags.enablePartialProgramFetch()) {
+                                // To skip already loaded complete data.
+                                Program currentProgramInfo =
+                                        mChannelIdCurrentProgramMap.get(program.getChannelId());
+                                if (currentProgramInfo != null
+                                        && Program.isDuplicate(program, currentProgramInfo)) {
+                                    program = currentProgramInfo;
+                                }
                             }
-
                             programMap.put(program.getChannelId(), programs);
                         }
                         programs.add(program);
@@ -701,12 +628,15 @@
                                         mLastPrefetchTaskRunMs + PROGRAM_GUIDE_SNAP_TIME_MS,
                                         PROGRAM_GUIDE_SNAP_TIME_MS)
                                 - currentTime;
+                // Issue second pre-fetch immediately after the first partial update
+                if (mChannelIdProgramCache.isEmpty()) {
+                    nextMessageDelayedTime = 0;
+                }
                 mChannelIdProgramCache = programs;
-                // Since cache has partial data we need to reset the map of complete data.
-                clearChannelInfoMap();
-                // Get complete projection of tuned channel.
-                prefetchChannel(mTunedChannelId);
-
+                if (mBackendKnobsFlags.enablePartialProgramFetch()) {
+                    // Since cache has partial data we need to reset the map of complete data.
+                    mCompleteInfoChannelIds.clear();
+                }
                 notifyProgramUpdated();
                 if (mFromEmptyCacheTimeEvent != null) {
                     mPerformanceMonitor.stopTimer(
@@ -724,11 +654,6 @@
         }
     }
 
-    private void clearChannelInfoMap() {
-        mCompleteInfoChannelIds.clear();
-        mMaxFetchHoursMs = FETCH_HOURS_MS;
-    }
-
     private long getFetchDuration() {
         if (mChannelIdProgramCache.isEmpty()) {
             return Math.max(1L, mBackendKnobsFlags.programGuideInitialFetchHours());
@@ -760,7 +685,7 @@
                     mDbExecutor,
                     mContext,
                     TvContract.buildProgramsUriForChannel(channelId, startTimeMs, endTimeMs),
-                    ProgramImpl.PROJECTION,
+                    Program.PROJECTION,
                     null,
                     null,
                     SORT_BY_TIME);
@@ -771,7 +696,7 @@
         protected ArrayList<Program> onQuery(Cursor c) {
             ArrayList<Program> programMap = new ArrayList<>();
             while (c.moveToNext()) {
-                Program program = ProgramImpl.fromCursor(c);
+                Program program = Program.fromCursor(c);
                 programMap.add(program);
             }
             return programMap;
@@ -780,7 +705,7 @@
         @Override
         protected void onPostExecute(ArrayList<Program> programs) {
             mChannelIdProgramCache.put(mChannelId, programs);
-            notifyChannelUpdated();
+            notifySingleChannelUpdated(mChannelId);
         }
     }
 
@@ -790,9 +715,9 @@
         }
     }
 
-    private void notifyChannelUpdated() {
+    private void notifySingleChannelUpdated(long channelId) {
         for (Callback callback : mCallbacks) {
-            callback.onChannelUpdated();
+            callback.onSingleChannelUpdated(channelId);
         }
     }
 
@@ -806,10 +731,10 @@
                             .appendQueryParameter(PARAM_START_TIME, String.valueOf(time))
                             .appendQueryParameter(PARAM_END_TIME, String.valueOf(time))
                             .build(),
-                    ProgramImpl.PROJECTION,
+                    Program.PROJECTION,
                     null,
                     null,
-                    SORT_BY_CHANNEL_ID);
+                    SORT_BY_TIME);
         }
 
         @Override
@@ -822,21 +747,17 @@
                     if (isCancelled()) {
                         return programs;
                     }
-                    Program program = ProgramImpl.fromCursor(c);
-                    // Only one program is expected per channel for this query
-                    // However, skip overlapping programs from same channel
-                    if (Program.sameChannel(program, lastReadProgram)
-                            && Program.isOverlapping(program, lastReadProgram)) {
+                    Program program = Program.fromCursor(c);
+                    if (Program.isDuplicate(program, lastReadProgram)) {
                         duplicateCount++;
                         continue;
                     } else {
                         lastReadProgram = program;
                     }
-
                     programs.add(program);
                 }
                 if (duplicateCount > 0) {
-                    Log.w(TAG, "Found " + duplicateCount + " overlapping programs");
+                    Log.w(TAG, "Found " + duplicateCount + " duplicate programs");
                 }
             }
             return programs;
@@ -856,7 +777,9 @@
                 for (Long channelId : removedChannelIds) {
                     if (mPrefetchEnabled) {
                         mChannelIdProgramCache.remove(channelId);
-                        mCompleteInfoChannelIds.remove(channelId);
+                        if (mBackendKnobsFlags.enablePartialProgramFetch()) {
+                            mCompleteInfoChannelIds.remove(channelId);
+                        }
                     }
                     mChannelIdCurrentProgramMap.remove(channelId);
                     notifyCurrentProgramUpdate(channelId, null);
@@ -874,7 +797,7 @@
                     mDbExecutor,
                     mContext,
                     TvContract.buildProgramsUriForChannel(channelId, time, time),
-                    ProgramImpl.PROJECTION,
+                    Program.PROJECTION,
                     null,
                     null,
                     SORT_BY_TIME);
@@ -885,7 +808,7 @@
         public Program onQuery(Cursor c) {
             Program program = null;
             if (c != null && c.moveToNext()) {
-                program = ProgramImpl.fromCursor(c);
+                program = Program.fromCursor(c);
             }
             return program;
         }
@@ -946,9 +869,6 @@
                         }
                         break;
                     }
-                case MSG_UPDATE_CONTENT_RATINGS:
-                    mTvInputManagerHelper.getContentRatingsManager().update();
-                    break;
                 default:
                     // Do nothing
             }
@@ -1012,7 +932,7 @@
 
     // Create dummy program which indicates data isn't loaded yet so DB query is required.
     private Program createDummyProgram(long startTimeMs, long endTimeMs) {
-        return new ProgramImpl.Builder()
+        return new Program.Builder()
                 .setChannelId(Channel.INVALID_ID)
                 .setStartTimeUtcMillis(startTimeMs)
                 .setEndTimeUtcMillis(endTimeMs)
diff --git a/src/com/android/tv/data/api/BaseProgram.java b/src/com/android/tv/data/api/BaseProgram.java
deleted file mode 100644
index 8acaf79..0000000
--- a/src/com/android/tv/data/api/BaseProgram.java
+++ /dev/null
@@ -1,141 +0,0 @@
-package com.android.tv.data.api;
-
-import android.content.Context;
-import android.media.tv.TvContentRating;
-import android.support.annotation.Nullable;
-import com.google.common.collect.ImmutableList;
-import java.util.Comparator;
-import java.util.Objects;
-
-/**
- * Base class for {@link com.android.tv.data.Program} and {@link
- * com.android.tv.dvr.data.RecordedProgram}.
- */
-public interface BaseProgram {
-
-    /**
-     * Comparator used to compare {@link BaseProgram} according to its season and episodes number.
-     * If a program's season or episode number is null, it will be consider "smaller" than programs
-     * with season or episode numbers.
-     */
-    Comparator<BaseProgram> EPISODE_COMPARATOR = new EpisodeComparator(false);
-    /**
-     * Comparator used to compare {@link BaseProgram} according to its season and episodes number
-     * with season numbers in a reversed order. If a program's season or episode number is null, it
-     * will be consider "smaller" than programs with season or episode numbers.
-     */
-    Comparator<BaseProgram> SEASON_REVERSED_EPISODE_COMPARATOR = new EpisodeComparator(true);
-
-    String COLUMN_SERIES_ID = "series_id";
-    String COLUMN_STATE = "state";
-
-    /** Compares two strings represent season numbers or episode numbers of programs. */
-    static int numberCompare(String s1, String s2) {
-        if (Objects.equals(s1, s2)) {
-            return 0;
-        } else if (s1 == null) {
-            return -1;
-        } else if (s2 == null) {
-            return 1;
-        } else if (s1.equals(s2)) {
-            return 0;
-        }
-        try {
-            return Integer.compare(Integer.parseInt(s1), Integer.parseInt(s2));
-        } catch (NumberFormatException e) {
-            return s1.compareTo(s2);
-        }
-    }
-
-    /** Generates the series ID for the other inputs than the tuner TV input. */
-    static String generateSeriesId(String packageName, String title) {
-        return packageName + "/" + title;
-    }
-
-    /** Returns ID of the program. */
-    long getId();
-
-    /** Returns the title of the program. */
-    String getTitle();
-
-    /** Returns the episode title. */
-    String getEpisodeTitle();
-
-    /** Returns the displayed title of the program episode. */
-    @Nullable
-    String getEpisodeDisplayTitle(Context context);
-
-    /**
-     * Returns the content description of the program episode, suitable for being spoken by an
-     * accessibility service.
-     */
-    String getEpisodeContentDescription(Context context);
-
-    /** Returns the description of the program. */
-    String getDescription();
-
-    /** Returns the long description of the program. */
-    String getLongDescription();
-
-    /** Returns the start time of the program in Milliseconds. */
-    long getStartTimeUtcMillis();
-
-    /** Returns the end time of the program in Milliseconds. */
-    long getEndTimeUtcMillis();
-
-    /** Returns the duration of the program in Milliseconds. */
-    long getDurationMillis();
-
-    /** Returns the series ID. */
-    @Nullable
-    String getSeriesId();
-
-    /** Returns the season number. */
-    String getSeasonNumber();
-
-    /** Returns the episode number. */
-    String getEpisodeNumber();
-
-    /** Returns URI of the program's poster. */
-    String getPosterArtUri();
-
-    /** Returns URI of the program's thumbnail. */
-    String getThumbnailUri();
-
-    /** Returns the array of the ID's of the canonical genres. */
-    int[] getCanonicalGenreIds();
-
-    /** Returns the array of content ratings. */
-    ImmutableList<TvContentRating> getContentRatings();
-
-    /** Returns channel's ID of the program. */
-    long getChannelId();
-
-    /** Returns if the program is valid. */
-    boolean isValid();
-
-    /** Checks whether the program is episodic or not. */
-    boolean isEpisodic();
-
-    /** Generates the series ID for the other inputs than the tuner TV input. */
-    class EpisodeComparator implements Comparator<BaseProgram> {
-        private final boolean mReversedSeason;
-
-        EpisodeComparator(boolean reversedSeason) {
-            mReversedSeason = reversedSeason;
-        }
-
-        @Override
-        public int compare(BaseProgram lhs, BaseProgram rhs) {
-            if (lhs == rhs) {
-                return 0;
-            }
-            int seasonNumberCompare = numberCompare(lhs.getSeasonNumber(), rhs.getSeasonNumber());
-            if (seasonNumberCompare != 0) {
-                return mReversedSeason ? -seasonNumberCompare : seasonNumberCompare;
-            } else {
-                return numberCompare(lhs.getEpisodeNumber(), rhs.getEpisodeNumber());
-            }
-        }
-    }
-}
diff --git a/src/com/android/tv/data/api/Program.java b/src/com/android/tv/data/api/Program.java
deleted file mode 100644
index f2221f6..0000000
--- a/src/com/android/tv/data/api/Program.java
+++ /dev/null
@@ -1,141 +0,0 @@
-package com.android.tv.data.api;
-
-import android.content.Context;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.support.annotation.Nullable;
-import android.support.annotation.UiThread;
-
-import com.android.tv.util.images.ImageLoader;
-
-import java.io.Serializable;
-import java.util.List;
-
-/** A convenience interface to create and insert program information entries into the database. */
-public interface Program extends BaseProgram, Comparable<Program> {
-
-    /** Returns {@code true} if the program is valid and {@code false} otherwise. */
-    static boolean isProgramValid(Program program) {
-        return program != null && program.isValid();
-    }
-
-    static boolean isDuplicate(Program p1, Program p2) {
-        if (p1 == null || p2 == null) {
-            return false;
-        }
-        return p1.getChannelId() == p2.getChannelId()
-                && p1.getStartTimeUtcMillis() == p2.getStartTimeUtcMillis()
-                && p1.getEndTimeUtcMillis() == p2.getEndTimeUtcMillis();
-    }
-
-    /** True if the start or end times overlap. */
-    static boolean isOverlapping(@Nullable Program p1, @Nullable Program p2) {
-        return p1 != null
-                && p2 != null
-                && p1.getStartTimeUtcMillis() < p2.getEndTimeUtcMillis()
-                && p1.getEndTimeUtcMillis() > p2.getStartTimeUtcMillis();
-    }
-
-    /** True if the channels IDs are the same. */
-    static boolean sameChannel(@Nullable Program p1, @Nullable Program p2) {
-        return p1 != null && p2 != null && p1.getChannelId() == p2.getChannelId();
-    }
-
-    /** Returns the package name of this program. */
-    String getPackageName();
-
-    /** Returns the season title */
-    String getSeasonTitle();
-
-    /** Gets the localized duration of the program */
-    String getDurationString(Context context);
-
-    int getVideoWidth();
-
-    int getVideoHeight();
-
-    /** Returns the list of Critic Scores for this program */
-    @Nullable
-    List<CriticScore> getCriticScores();
-
-    /** Returns {@code true} if the recording of this program is prohibited. */
-    boolean isRecordingProhibited();
-
-    /** Returns array of canonical genres for this program. This is expected to be called rarely. */
-    @Nullable
-    String[] getCanonicalGenres();
-
-    /** Returns if this program has the genre. */
-    boolean hasGenre(int genreId);
-
-    /** Prefetch the program poster art. */
-    void prefetchPosterArt(Context context, int posterArtWidth, int posterArtHeight);
-
-    /**
-     * 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
-    boolean loadPosterArt(
-            Context context,
-            int posterArtWidth,
-            int posterArtHeight,
-            ImageLoader.ImageLoaderCallback<?> callback);
-
-    /** Returns a {@link Parcelable} representation of this instance. */
-    Parcelable toParcelable();
-
-    /** Holds one type of critic score and its source. */
-    final class CriticScore implements Serializable, Parcelable {
-        /** The source of the rating. */
-        public final String source;
-        /** The score. */
-        public final String score;
-        /** The url of the logo image */
-        public final String logoUrl;
-
-        public static final Creator<CriticScore> CREATOR =
-                new Creator<CriticScore>() {
-                    @Override
-                    public CriticScore createFromParcel(Parcel in) {
-                        String source = in.readString();
-                        String score = in.readString();
-                        String logoUri = in.readString();
-                        return new CriticScore(source, score, logoUri);
-                    }
-
-                    @Override
-                    public CriticScore[] newArray(int size) {
-                        return new CriticScore[size];
-                    }
-                };
-
-        /**
-         * Constructor for this class.
-         *
-         * @param source the source of the rating
-         * @param score the score
-         */
-        public CriticScore(String source, String score, String logoUrl) {
-            this.source = source;
-            this.score = score;
-            this.logoUrl = logoUrl;
-        }
-
-        @Override
-        public int describeContents() {
-            return 0;
-        }
-
-        @Override
-        public void writeToParcel(Parcel out, int i) {
-            out.writeString(source);
-            out.writeString(score);
-            out.writeString(logoUrl);
-        }
-    }
-}
diff --git a/src/com/android/tv/data/epg/EpgFetchHelper.java b/src/com/android/tv/data/epg/EpgFetchHelper.java
index 4e88911..3843ca9 100644
--- a/src/com/android/tv/data/epg/EpgFetchHelper.java
+++ b/src/com/android/tv/data/epg/EpgFetchHelper.java
@@ -28,15 +28,12 @@
 import android.support.annotation.WorkerThread;
 import android.text.TextUtils;
 import android.util.Log;
-
 import com.android.tv.common.CommonConstants;
 import com.android.tv.common.util.Clock;
-import com.android.tv.data.ProgramImpl;
+import com.android.tv.data.Program;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
 import com.android.tv.features.TvFeatures;
 import com.android.tv.util.TvProviderUtils;
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -109,7 +106,7 @@
                     ops.add(
                             ContentProviderOperation.newUpdate(
                                             TvContract.buildProgramUri(oldProgram.getId()))
-                                    .withValues(ProgramImpl.toContentValues(newProgram, context))
+                                    .withValues(Program.toContentValues(newProgram, context))
                                     .build());
                     oldProgramsIndex++;
                     newProgramsIndex++;
@@ -135,7 +132,7 @@
             if (addNewProgram) {
                 ops.add(
                         ContentProviderOperation.newInsert(Programs.CONTENT_URI)
-                                .withValues(ProgramImpl.toContentValues(newProgram, context))
+                                .withValues(Program.toContentValues(newProgram, context))
                                 .build());
             }
             // Throttle the batch operation not to cause TransactionTooLargeException.
@@ -202,7 +199,7 @@
     @WorkerThread
     private static List<Program> queryPrograms(
             Context context, long channelId, long startTimeMs, long endTimeMs) {
-        String[] projection = ProgramImpl.PROJECTION;
+        String[] projection = Program.PROJECTION;
         if (TvProviderUtils.checkSeriesIdColumn(context, Programs.CONTENT_URI)) {
             projection =
                     TvProviderUtils.addExtraColumnsToProjection(
@@ -222,7 +219,7 @@
             }
             ArrayList<Program> programs = new ArrayList<>();
             while (c.moveToNext()) {
-                programs.add(ProgramImpl.fromCursor(c));
+                programs.add(Program.fromCursor(c));
             }
             return programs;
         }
diff --git a/src/com/android/tv/data/epg/EpgFetchService.java b/src/com/android/tv/data/epg/EpgFetchService.java
index cfa79cb..aa4f358 100644
--- a/src/com/android/tv/data/epg/EpgFetchService.java
+++ b/src/com/android/tv/data/epg/EpgFetchService.java
@@ -18,24 +18,22 @@
 
 import android.app.job.JobParameters;
 import android.app.job.JobService;
-
 import com.android.tv.Starter;
+import com.android.tv.TvSingletons;
 import com.android.tv.data.ChannelDataManager;
 
-import dagger.android.AndroidInjection;
-
-import javax.inject.Inject;
-
 /** JobService to Fetch EPG data. */
 public class EpgFetchService extends JobService {
-    @Inject EpgFetcher mEpgFetcher;
-    @Inject ChannelDataManager mChannelDataManager;
+    private EpgFetcher mEpgFetcher;
+    private ChannelDataManager mChannelDataManager;
 
     @Override
     public void onCreate() {
-        AndroidInjection.inject(this);
         super.onCreate();
         Starter.start(this);
+        TvSingletons tvSingletons = TvSingletons.getSingletons(getApplicationContext());
+        mEpgFetcher = tvSingletons.getEpgFetcher();
+        mChannelDataManager = tvSingletons.getChannelDataManager();
     }
 
     @Override
diff --git a/src/com/android/tv/data/epg/EpgFetcherImpl.java b/src/com/android/tv/data/epg/EpgFetcherImpl.java
index 27d7f8d..b191421 100644
--- a/src/com/android/tv/data/epg/EpgFetcherImpl.java
+++ b/src/com/android/tv/data/epg/EpgFetcherImpl.java
@@ -38,12 +38,10 @@
 import android.support.annotation.WorkerThread;
 import android.text.TextUtils;
 import android.util.Log;
-
 import com.android.tv.TvSingletons;
 import com.android.tv.common.BuildConfig;
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.common.buildtype.HasBuildType;
-import com.android.tv.common.dagger.annotations.ApplicationContext;
 import com.android.tv.common.util.Clock;
 import com.android.tv.common.util.CommonUtils;
 import com.android.tv.common.util.LocationUtils;
@@ -54,22 +52,17 @@
 import com.android.tv.data.ChannelImpl;
 import com.android.tv.data.ChannelLogoFetcher;
 import com.android.tv.data.Lineup;
+import com.android.tv.data.Program;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
-import com.android.tv.data.epg.EpgReader.EpgChannel;
 import com.android.tv.features.TvFeatures;
 import com.android.tv.perf.EventNames;
 import com.android.tv.perf.PerformanceMonitor;
 import com.android.tv.perf.TimerEvent;
 import com.android.tv.util.Utils;
-
 import com.google.android.tv.partner.support.EpgInput;
 import com.google.android.tv.partner.support.EpgInputs;
 import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-
 import com.android.tv.common.flags.BackendKnobsFlags;
-
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -80,8 +73,6 @@
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
 
-import javax.inject.Inject;
-
 /**
  * The service class to fetch EPG routinely or on-demand during channel scanning
  *
@@ -118,6 +109,7 @@
     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 final Context mContext;
@@ -138,9 +130,31 @@
 
     private Clock mClock;
 
-    @Inject
-    public EpgFetcherImpl(
-            @ApplicationContext Context context,
+    public static EpgFetcher create(Context context) {
+        context = context.getApplicationContext();
+        TvSingletons tvSingletons = TvSingletons.getSingletons(context);
+        ChannelDataManager channelDataManager = tvSingletons.getChannelDataManager();
+        PerformanceMonitor performanceMonitor = tvSingletons.getPerformanceMonitor();
+        EpgReader epgReader = tvSingletons.providesEpgReader().get();
+        Clock clock = tvSingletons.getClock();
+        EpgInputWhiteList epgInputWhiteList =
+                new EpgInputWhiteList(tvSingletons.getCloudEpgFlags());
+        BackendKnobsFlags backendKnobsFlags = tvSingletons.getBackendKnobs();
+        HasBuildType.BuildType buildType = tvSingletons.getBuildType();
+        return new EpgFetcherImpl(
+                context,
+                epgInputWhiteList,
+                channelDataManager,
+                epgReader,
+                performanceMonitor,
+                clock,
+                backendKnobsFlags,
+                buildType);
+    }
+
+    @VisibleForTesting
+    EpgFetcherImpl(
+            Context context,
             EpgInputWhiteList epgInputWhiteList,
             ChannelDataManager channelDataManager,
             EpgReader epgReader,
@@ -455,16 +469,23 @@
         if (epgChannels.size() == 0) {
             return;
         }
-        int batchSize = (int) Math.max(1, mBackendKnobsFlags.epgFetcherChannelsPerProgramFetch());
-        for (Iterable<EpgChannel> batch : Iterables.partition(epgChannels, batchSize)) {
-            batchUpdateEpg(mEpgReader.getPrograms(ImmutableSet.copyOf(batch), durationSec));
+        Set<EpgReader.EpgChannel> batch = new HashSet<>(QUERY_CHANNEL_COUNT);
+        for (EpgReader.EpgChannel epgChannel : epgChannels) {
+            batch.add(epgChannel);
+            if (batch.size() >= QUERY_CHANNEL_COUNT) {
+                batchUpdateEpg(mEpgReader.getPrograms(batch, durationSec));
+                batch.clear();
+            }
+        }
+        if (!batch.isEmpty()) {
+            batchUpdateEpg(mEpgReader.getPrograms(batch, durationSec));
         }
     }
 
     @WorkerThread
     private void batchUpdateEpg(Map<EpgReader.EpgChannel, Collection<Program>> allPrograms) {
         for (Map.Entry<EpgReader.EpgChannel, Collection<Program>> entry : allPrograms.entrySet()) {
-            List<Program> programs = new ArrayList<>(entry.getValue());
+            List<Program> programs = new ArrayList(entry.getValue());
             if (programs == null) {
                 continue;
             }
@@ -583,7 +604,6 @@
                             ? ((Integer) REASON_CLOUD_EPG_FAILURE)
                             : anyCloudEpgSuccess ? null : builtInResult;
                 }
-                clearUnusedLineups(null);
                 return builtInResult;
             } finally {
                 TrafficStats.setThreadStatsTag(oldTag);
diff --git a/src/com/android/tv/data/epg/EpgInputWhiteList.java b/src/com/android/tv/data/epg/EpgInputWhiteList.java
index 4a5f98b..24b4fe3 100644
--- a/src/com/android/tv/data/epg/EpgInputWhiteList.java
+++ b/src/com/android/tv/data/epg/EpgInputWhiteList.java
@@ -21,14 +21,13 @@
 import android.text.TextUtils;
 import android.util.Log;
 import com.android.tv.common.BuildConfig;
+import com.android.tv.common.experiments.Experiments;
 import com.android.tv.common.flags.CloudEpgFlags;
-import com.android.tv.common.flags.LegacyFlags;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
-import javax.inject.Inject;
 
 /** Checks if a package or a input is white listed. */
 public final class EpgInputWhiteList {
@@ -37,7 +36,6 @@
     private static final String QA_DEV_INPUTS =
             "com.example.partnersupportsampletvinput/.SampleTvInputService,"
                     + "com.android.tv.tuner.sample.dvb/.tvinput.SampleDvbTunerTvInputService";
-    private final LegacyFlags mLegacyFlags;
 
     /** Returns the package portion of a inputId */
     @Nullable
@@ -45,12 +43,10 @@
         return inputId == null ? null : inputId.substring(0, inputId.indexOf("/"));
     }
 
-    private final CloudEpgFlags mCloudEpgFlags;
+    private final CloudEpgFlags cloudEpgFlags;
 
-    @Inject
-    public EpgInputWhiteList(CloudEpgFlags cloudEpgFlags, LegacyFlags legacyFlags) {
-        mCloudEpgFlags = cloudEpgFlags;
-        mLegacyFlags = legacyFlags;
+    public EpgInputWhiteList(CloudEpgFlags cloudEpgFlags) {
+        this.cloudEpgFlags = cloudEpgFlags;
     }
 
     public boolean isInputWhiteListed(String inputId) {
@@ -75,8 +71,8 @@
     }
 
     private Set<String> getWhiteListedInputs() {
-        Set<String> result = toInputSet(mCloudEpgFlags.thirdPartyEpgInputsCsv());
-        if (BuildConfig.ENG || mLegacyFlags.enableQaFeatures()) {
+        Set<String> result = toInputSet(cloudEpgFlags.thirdPartyEpgInputsCsv());
+        if (BuildConfig.ENG || Experiments.ENABLE_QA_FEATURES.get()) {
             HashSet<String> moreInputs = new HashSet<>(toInputSet(QA_DEV_INPUTS));
             if (result.isEmpty()) {
                 result = moreInputs;
diff --git a/src/com/android/tv/data/epg/EpgReader.java b/src/com/android/tv/data/epg/EpgReader.java
index 8c0e3f0..c9fcd97 100644
--- a/src/com/android/tv/data/epg/EpgReader.java
+++ b/src/com/android/tv/data/epg/EpgReader.java
@@ -19,14 +19,11 @@
 import android.support.annotation.AnyThread;
 import android.support.annotation.NonNull;
 import android.support.annotation.WorkerThread;
-
 import com.android.tv.data.Lineup;
+import com.android.tv.data.Program;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
 import com.android.tv.dvr.data.SeriesInfo;
-
 import com.google.auto.value.AutoValue;
-
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
@@ -39,8 +36,8 @@
     /** Value class that holds a EpgChannelId and its corresponding {@link Channel} */
     @AutoValue
     abstract class EpgChannel {
-        public static EpgChannel createEpgChannel(
-                Channel channel, String epgChannelId, boolean dbUpdateNeeded) {
+        public static EpgChannel createEpgChannel(Channel channel, String epgChannelId,
+                boolean dbUpdateNeeded) {
             return new AutoValue_EpgReader_EpgChannel(channel, epgChannelId, dbUpdateNeeded);
         }
 
diff --git a/src/com/android/tv/data/epg/StubEpgReader.java b/src/com/android/tv/data/epg/StubEpgReader.java
index 19bf786..3b00148 100644
--- a/src/com/android/tv/data/epg/StubEpgReader.java
+++ b/src/com/android/tv/data/epg/StubEpgReader.java
@@ -16,25 +16,21 @@
 
 package com.android.tv.data.epg;
 
+import android.content.Context;
 import android.support.annotation.NonNull;
-
 import com.android.tv.data.Lineup;
+import com.android.tv.data.Program;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
 import com.android.tv.dvr.data.SeriesInfo;
-
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import javax.inject.Inject;
-
 /** A stub class to read EPG. */
 public class StubEpgReader implements EpgReader {
-    @Inject
-    public StubEpgReader() {}
+    public StubEpgReader(@SuppressWarnings("unused") Context context) {}
 
     @Override
     public boolean isAvailable() {
diff --git a/src/com/android/tv/dialog/PinDialogFragment.java b/src/com/android/tv/dialog/PinDialogFragment.java
index c714558..8730809 100644
--- a/src/com/android/tv/dialog/PinDialogFragment.java
+++ b/src/com/android/tv/dialog/PinDialogFragment.java
@@ -18,7 +18,6 @@
 
 import android.app.ActivityManager;
 import android.app.Dialog;
-import android.content.Context;
 import android.content.DialogInterface;
 import android.content.SharedPreferences;
 import android.media.tv.TvContentRating;
@@ -34,13 +33,10 @@
 import android.widget.TextView;
 import android.widget.Toast;
 import com.android.tv.R;
+import com.android.tv.TvSingletons;
 import com.android.tv.common.SoftPreconditions;
-import com.android.tv.dialog.picker.TvPinPicker;
-import com.android.tv.util.TvInputManagerHelper;
+import com.android.tv.dialog.picker.PinPicker;
 import com.android.tv.util.TvSettings;
-import dagger.android.AndroidInjection;
-import com.android.tv.common.flags.UiFlags;
-import javax.inject.Inject;
 
 public class PinDialogFragment extends SafeDismissDialogFragment {
     private static final String TAG = "PinDialogFragment";
@@ -84,8 +80,7 @@
     private TextView mWrongPinView;
     private View mEnterPinView;
     private TextView mTitleView;
-
-    private TvPinPicker mTvPinPicker;
+    private PinPicker mPicker;
     private SharedPreferences mSharedPreferences;
     private String mPrevPin;
     private String mPin;
@@ -93,8 +88,6 @@
     private int mWrongPinCount;
     private long mDisablePinUntil;
     private final Handler mHandler = new Handler();
-    @Inject TvInputManagerHelper mTvInputManagerHelper;
-    @Inject UiFlags mUiFlags;
 
     public static PinDialogFragment create(int type) {
         return create(type, null);
@@ -110,12 +103,6 @@
     }
 
     @Override
-    public void onAttach(Context context) {
-        AndroidInjection.inject(this);
-        super.onAttach(context);
-    }
-
-    @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         mRequestType = getArguments().getInt(ARGS_TYPE, PIN_DIALOG_TYPE_ENTER_PIN);
@@ -167,8 +154,8 @@
         mWrongPinView = (TextView) v.findViewById(R.id.wrong_pin);
         mEnterPinView = v.findViewById(R.id.enter_pin);
         mTitleView = (TextView) mEnterPinView.findViewById(R.id.title);
-        mTvPinPicker = v.findViewById(R.id.tv_pin_picker);
-        mTvPinPicker.setOnClickListener(
+        mPicker = v.findViewById(R.id.pin_picker);
+        mPicker.setOnClickListener(
                 view -> {
                     String pin = getPinInput();
                     if (!TextUtils.isEmpty(pin)) {
@@ -196,7 +183,8 @@
                     mTitleView.setText(
                             getString(
                                     R.string.pin_enter_unlock_dvr,
-                                    mTvInputManagerHelper
+                                    TvSingletons.getSingletons(getContext())
+                                            .getTvInputManagerHelper()
                                             .getContentRatingsManager()
                                             .getDisplayNameForRating(tvContentRating)));
                 }
@@ -216,8 +204,7 @@
         if (mType != PIN_DIALOG_TYPE_NEW_PIN) {
             updateWrongPin();
         }
-
-        mTvPinPicker.requestFocus();
+        mPicker.requestFocus();
         return v;
     }
 
@@ -351,11 +338,11 @@
     }
 
     private String getPinInput() {
-        return mTvPinPicker.getPin();
+        return mPicker.getPinInput();
     }
 
     private void resetPinInput() {
-        mTvPinPicker.resetPin();
+        mPicker.resetPinInput();
     }
 
     /**
diff --git a/src/com/android/tv/dialog/picker/PinPicker.java b/src/com/android/tv/dialog/picker/PinPicker.java
new file mode 100644
index 0000000..f501dfd
--- /dev/null
+++ b/src/com/android/tv/dialog/picker/PinPicker.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2018 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.picker;
+
+import android.content.Context;
+import android.support.annotation.Nullable;
+import android.support.annotation.VisibleForTesting;
+import android.support.v17.leanback.widget.picker.Picker;
+import android.support.v17.leanback.widget.picker.PickerColumn;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import java.util.ArrayList;
+import java.util.List;
+
+/** 4 digit picker */
+public final class PinPicker extends Picker {
+    // TODO(b/116144491): use leanback pin picker.
+
+    private final List<PickerColumn> mPickers = new ArrayList<>();
+    private OnClickListener mOnClickListener;
+
+    // the version of picker I link to does not have this constructor
+    public PinPicker(Context context, AttributeSet attributeSet) {
+        this(context, attributeSet, 0);
+    }
+
+    public PinPicker(Context context, AttributeSet attributeSet, int defStyleAttr) {
+        super(context, attributeSet, defStyleAttr);
+
+        for (int i = 0; i < 4; i++) {
+            PickerColumn pickerColumn = new PickerColumn();
+            pickerColumn.setMinValue(0);
+            pickerColumn.setMaxValue(9);
+            pickerColumn.setLabelFormat("%d");
+            mPickers.add(pickerColumn);
+        }
+        setSeparator(" ");
+        setColumns(mPickers);
+        setActivated(true);
+        setFocusable(true);
+        super.setOnClickListener(this::onClick);
+    }
+
+    public String getPinInput() {
+        String result = "";
+        try {
+            for (PickerColumn column : mPickers) {
+
+                result += column.getCurrentValue();
+            }
+        } catch (IllegalStateException e) {
+            result = "";
+        }
+        return result;
+    }
+
+    @Override
+    public void setOnClickListener(@Nullable OnClickListener l) {
+        mOnClickListener = l;
+    }
+
+    private void onClick(View v) {
+        int selectedColumn = getSelectedColumn();
+        int nextColumn = selectedColumn + 1;
+        // Only call the click listener if we are on the last column
+        // Otherwise move to the next column
+        if (nextColumn == getColumnsCount()) {
+            if (mOnClickListener != null) {
+                mOnClickListener.onClick(v);
+            }
+        } else {
+            setSelectedColumn(nextColumn);
+            onRequestFocusInDescendants(ViewGroup.FOCUS_FORWARD, null);
+        }
+    }
+
+    public void resetPinInput() {
+        setActivated(false);
+        for (int i = 0; i < 4; i++) {
+            setColumnValue(i, 0, true);
+        }
+        setSelectedColumn(0);
+        setActivated(true); // This resets the focus
+    }
+
+    @Override
+    public boolean dispatchKeyEvent(KeyEvent event) {
+        if (event.getAction() == KeyEvent.ACTION_UP) {
+            int keyCode = event.getKeyCode();
+            int digit = digitFromKeyCode(keyCode);
+            if (digit != -1) {
+                int selectedColumn = getSelectedColumn();
+                setColumnValue(selectedColumn, digit, false);
+                int nextColumn = selectedColumn + 1;
+                if (nextColumn < getColumnsCount()) {
+                    setSelectedColumn(nextColumn);
+                    onRequestFocusInDescendants(ViewGroup.FOCUS_FORWARD, null);
+                } else {
+                    callOnClick();
+                }
+                return true;
+            }
+        }
+        return super.dispatchKeyEvent(event);
+    }
+
+    @VisibleForTesting
+    static int digitFromKeyCode(int keyCode) {
+        if (keyCode >= KeyEvent.KEYCODE_0 && keyCode <= KeyEvent.KEYCODE_9) {
+            return keyCode - KeyEvent.KEYCODE_0;
+        } else if (keyCode >= KeyEvent.KEYCODE_NUMPAD_0 && keyCode <= KeyEvent.KEYCODE_NUMPAD_9) {
+            return keyCode - KeyEvent.KEYCODE_NUMPAD_0;
+        }
+        return -1;
+    }
+}
diff --git a/src/com/android/tv/dialog/picker/TvPinPicker.java b/src/com/android/tv/dialog/picker/TvPinPicker.java
deleted file mode 100644
index 064b7f0..0000000
--- a/src/com/android/tv/dialog/picker/TvPinPicker.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2019 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.picker;
-
-import static android.content.Context.ACCESSIBILITY_SERVICE;
-
-import android.content.Context;
-import androidx.leanback.widget.picker.PinPicker;
-import android.util.AttributeSet;
-import android.view.accessibility.AccessibilityManager;
-
-/** 4 digit picker */
-public final class TvPinPicker extends PinPicker {
-
-    private boolean mSkipPerformClick = true;
-    private boolean mIsAccessibilityEnabled = false;
-
-    public TvPinPicker(Context context, AttributeSet attributeSet) {
-        this(context, attributeSet, 0);
-    }
-
-    public TvPinPicker(Context context, AttributeSet attributeSet, int defStyleAttr) {
-        super(context, attributeSet, defStyleAttr);
-        setActivated(true);
-        AccessibilityManager am =
-                (AccessibilityManager) context.getSystemService(ACCESSIBILITY_SERVICE);
-        mIsAccessibilityEnabled = am.isEnabled();
-    }
-
-    @Override
-    public boolean performClick() {
-        // (b/120096347) Skip first click when talkback is enabled
-        if (mSkipPerformClick && mIsAccessibilityEnabled) {
-            mSkipPerformClick = false;
-            /* Force focus to next value */
-            setColumnValue(getSelectedColumn(), 1, true);
-            return false;
-        }
-        return super.performClick();
-    }
-}
diff --git a/src/com/android/tv/dvr/DvrDataManagerImpl.java b/src/com/android/tv/dvr/DvrDataManagerImpl.java
index 3e26a23..0053650 100644
--- a/src/com/android/tv/dvr/DvrDataManagerImpl.java
+++ b/src/com/android/tv/dvr/DvrDataManagerImpl.java
@@ -37,10 +37,8 @@
 import android.util.ArraySet;
 import android.util.Log;
 import android.util.Range;
-
 import com.android.tv.TvSingletons;
 import com.android.tv.common.SoftPreconditions;
-import com.android.tv.common.dagger.annotations.ApplicationContext;
 import com.android.tv.common.recording.RecordingStorageStatusManager;
 import com.android.tv.common.recording.RecordingStorageStatusManager.OnStorageMountChangedListener;
 import com.android.tv.common.util.Clock;
@@ -50,7 +48,6 @@
 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.DvrDatabaseHelper;
 import com.android.tv.dvr.provider.DvrDbFuture.AddScheduleFuture;
 import com.android.tv.dvr.provider.DvrDbFuture.AddSeriesRecordingFuture;
 import com.android.tv.dvr.provider.DvrDbFuture.DeleteScheduleFuture;
@@ -63,14 +60,11 @@
 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.AsyncDbTask.DbExecutor;
 import com.android.tv.util.TvInputManagerHelper;
 import com.android.tv.util.TvUriMatcher;
-
 import com.google.common.base.Predicate;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.ListenableFuture;
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -82,13 +76,9 @@
 import java.util.concurrent.Executor;
 import java.util.concurrent.Future;
 
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
 /** DVR Data manager to handle recordings and schedules. */
 @MainThread
 @TargetApi(Build.VERSION_CODES.N)
-@Singleton
 public class DvrDataManagerImpl extends BaseDvrDataManager {
     private static final String TAG = "DvrDataManagerImpl";
     private static final boolean DEBUG = false;
@@ -108,7 +98,6 @@
     private final HashMap<Long, SeriesRecording> mSeriesRecordingsForRemovedInput = new HashMap<>();
 
     private final Context mContext;
-    private final DvrDatabaseHelper mDbHelper;
     private Executor mDbExecutor;
     private final ContentObserver mContentObserver =
             new ContentObserver(new Handler(Looper.getMainLooper())) {
@@ -198,28 +187,20 @@
         return moved;
     }
 
-    @Inject
-    public DvrDataManagerImpl(
-            @ApplicationContext Context context,
-            Clock clock,
-            TvInputManagerHelper tvInputManagerHelper,
-            @DbExecutor Executor dbExecutor,
-            DvrDatabaseHelper dbHelper) {
+    public DvrDataManagerImpl(Context context, Clock clock) {
         super(context, clock);
         mContext = context;
         TvSingletons tvSingletons = TvSingletons.getSingletons(context);
-        mInputManager = tvInputManagerHelper;
+        mInputManager = tvSingletons.getTvInputManagerHelper();
         mStorageStatusManager = tvSingletons.getRecordingStorageStatusManager();
-        mDbExecutor = dbExecutor;
-        mDbHelper = dbHelper;
-        start();
+        mDbExecutor = tvSingletons.getDbExecutor();
     }
 
-    private void start() {
+    public void start() {
         mInputManager.addCallback(mInputCallback);
         mStorageStatusManager.addListener(mStorageMountChangedListener);
         DvrQuerySeriesRecordingFuture dvrQuerySeriesRecordingTask =
-                new DvrQuerySeriesRecordingFuture(mDbHelper);
+                new DvrQuerySeriesRecordingFuture(mContext);
         ListenableFuture<List<SeriesRecording>> dvrQuerySeriesRecordingFuture =
                 dvrQuerySeriesRecordingTask.executeOnDbThread(
                         new FutureCallback<List<SeriesRecording>>() {
@@ -232,8 +213,7 @@
                                     if (SoftPreconditions.checkState(
                                             !seriesIds.contains(r.getSeriesId()),
                                             TAG,
-                                            "Skip loading series recording with duplicate series"
-                                                    + " ID: "
+                                            "Skip loading series recording with duplicate series ID: "
                                                     + r)) {
                                         seriesIds.add(r.getSeriesId());
                                         if (isInputAvailable(r.getInputId())) {
@@ -257,7 +237,7 @@
                             }
                         });
         mPendingDvrFuture.add(dvrQuerySeriesRecordingFuture);
-        DvrQueryScheduleFuture dvrQueryScheduleTask = new DvrQueryScheduleFuture(mDbHelper);
+        DvrQueryScheduleFuture dvrQueryScheduleTask = new DvrQueryScheduleFuture(mContext);
         ListenableFuture<List<ScheduledRecording>> dvrQueryScheduleFuture =
                 dvrQueryScheduleTask.executeOnDbThread(
                         new FutureCallback<List<ScheduledRecording>>() {
@@ -661,7 +641,7 @@
             notifyScheduledRecordingAdded(schedules);
         }
         ListenableFuture addScheduleFuture =
-                new AddScheduleFuture(mDbHelper)
+                new AddScheduleFuture(mContext)
                         .executeOnDbThread(removeFromSetOnCompletion, schedules);
         mNoStopFuture.add(addScheduleFuture);
         removeDeletedSchedules(schedules);
@@ -683,7 +663,7 @@
             notifySeriesRecordingAdded(seriesRecordings);
         }
         ListenableFuture addSeriesRecordingFuture =
-                new AddSeriesRecordingFuture(mDbHelper)
+                new AddSeriesRecordingFuture(mContext)
                         .executeOnDbThread(removeFromSetOnCompletion, seriesRecordings);
         mNoStopFuture.add(addSeriesRecordingFuture);
     }
@@ -743,7 +723,7 @@
         }
         if (!schedulesToDelete.isEmpty()) {
             ListenableFuture deleteScheduleFuture =
-                    new DeleteScheduleFuture(mDbHelper)
+                    new DeleteScheduleFuture(mContext)
                             .executeOnDbThread(
                                     removeFromSetOnCompletion,
                                     ScheduledRecording.toArray(schedulesToDelete));
@@ -751,7 +731,7 @@
         }
         if (!schedulesNotToDelete.isEmpty()) {
             ListenableFuture updateScheduleFuture =
-                    new UpdateScheduleFuture(mDbHelper)
+                    new UpdateScheduleFuture(mContext)
                             .executeOnDbThread(
                                     removeFromSetOnCompletion,
                                     ScheduledRecording.toArray(schedulesNotToDelete));
@@ -794,7 +774,7 @@
             notifySeriesRecordingRemoved(seriesRecordings);
         }
         ListenableFuture deleteSeriesRecordingFuture =
-                new DeleteSeriesRecordingFuture(mDbHelper)
+                new DeleteSeriesRecordingFuture(mContext)
                         .executeOnDbThread(removeFromSetOnCompletion, seriesRecordings);
         mNoStopFuture.add(deleteSeriesRecordingFuture);
         removeDeletedSchedules(seriesRecordings);
@@ -849,7 +829,7 @@
         }
         if (updateDb) {
             ListenableFuture updateScheduleFuture =
-                    new UpdateScheduleFuture(mDbHelper)
+                    new UpdateScheduleFuture(mContext)
                             .executeOnDbThread(removeFromSetOnCompletion, scheduleArray);
             mNoStopFuture.add(updateScheduleFuture);
         }
@@ -876,7 +856,7 @@
             notifySeriesRecordingChanged(seriesRecordings);
         }
         ListenableFuture updateSeriesRecordingFuture =
-                new UpdateSeriesRecordingFuture(mDbHelper)
+                new UpdateSeriesRecordingFuture(mContext)
                         .executeOnDbThread(removeFromSetOnCompletion, seriesRecordings);
         mNoStopFuture.add(updateSeriesRecordingFuture);
     }
@@ -897,7 +877,7 @@
         }
         if (!schedulesToDelete.isEmpty()) {
             ListenableFuture deleteScheduleFuture =
-                    new DeleteScheduleFuture(mDbHelper)
+                    new DeleteScheduleFuture(mContext)
                             .executeOnDbThread(
                                     removeFromSetOnCompletion,
                                     ScheduledRecording.toArray(schedulesToDelete));
@@ -922,7 +902,7 @@
         }
         if (!schedulesToDelete.isEmpty()) {
             ListenableFuture deleteScheduleFuture =
-                    new DeleteScheduleFuture(mDbHelper)
+                    new DeleteScheduleFuture(mContext)
                             .executeOnDbThread(
                                     removeFromSetOnCompletion,
                                     ScheduledRecording.toArray(schedulesToDelete));
@@ -970,7 +950,7 @@
             mSeriesRecordingsForRemovedInput.remove(r.getId());
         }
         ListenableFuture deleteSeriesRecordingFuture =
-                new DeleteSeriesRecordingFuture(mDbHelper)
+                new DeleteSeriesRecordingFuture(mContext)
                         .executeOnDbThread(
                                 removeFromSetOnCompletion,
                                 SeriesRecording.toArray(removedSeriesRecordings));
@@ -1063,13 +1043,13 @@
             }
         }
         ListenableFuture deleteScheduleFuture =
-                new DeleteScheduleFuture(mDbHelper)
+                new DeleteScheduleFuture(mContext)
                         .executeOnDbThread(
                                 removeFromSetOnCompletion,
                                 ScheduledRecording.toArray(schedulesToDelete));
         mNoStopFuture.add(deleteScheduleFuture);
         ListenableFuture deleteSeriesRecordingFuture =
-                new DeleteSeriesRecordingFuture(mDbHelper)
+                new DeleteSeriesRecordingFuture(mContext)
                         .executeOnDbThread(
                                 removeFromSetOnCompletion,
                                 SeriesRecording.toArray(seriesRecordingsToDelete));
@@ -1105,7 +1085,7 @@
         if (!removedSeriesRecordings.isEmpty()) {
             SeriesRecording[] removed = SeriesRecording.toArray(removedSeriesRecordings);
             ListenableFuture deleteSeriesRecordingFuture =
-                    new DeleteSeriesRecordingFuture(mDbHelper)
+                    new DeleteSeriesRecordingFuture(mContext)
                             .executeOnDbThread(removeFromSetOnCompletion, removed);
             mNoStopFuture.add(deleteSeriesRecordingFuture);
             if (mDvrLoadFinished) {
diff --git a/src/com/android/tv/dvr/DvrManager.java b/src/com/android/tv/dvr/DvrManager.java
index 12982c6..cc9ad37 100644
--- a/src/com/android/tv/dvr/DvrManager.java
+++ b/src/com/android/tv/dvr/DvrManager.java
@@ -37,13 +37,12 @@
 import android.support.annotation.WorkerThread;
 import android.util.Log;
 import android.util.Range;
-
 import com.android.tv.TvSingletons;
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.common.feature.CommonFeatures;
 import com.android.tv.common.util.CommonUtils;
+import com.android.tv.data.Program;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
 import com.android.tv.dvr.DvrDataManager.OnRecordedProgramLoadFinishedListener;
 import com.android.tv.dvr.DvrDataManager.RecordedProgramListener;
 import com.android.tv.dvr.DvrScheduleManager.OnInitializeListener;
@@ -52,7 +51,6 @@
 import com.android.tv.dvr.data.SeriesRecording;
 import com.android.tv.util.AsyncDbTask;
 import com.android.tv.util.Utils;
-
 import java.io.File;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -189,7 +187,7 @@
                         ? mScheduleManager.suggestNewPriority()
                         : mScheduleManager.suggestHighestPriority(
                                 seriesRecording.getInputId(),
-                                Range.create(
+                                new Range(
                                         program.getStartTimeUtcMillis(),
                                         program.getEndTimeUtcMillis()),
                                 seriesRecording.getPriority()));
diff --git a/src/com/android/tv/dvr/DvrScheduleManager.java b/src/com/android/tv/dvr/DvrScheduleManager.java
index 3afcc42..7202dce 100644
--- a/src/com/android/tv/dvr/DvrScheduleManager.java
+++ b/src/com/android/tv/dvr/DvrScheduleManager.java
@@ -25,12 +25,11 @@
 import android.support.annotation.VisibleForTesting;
 import android.util.ArraySet;
 import android.util.Range;
-
 import com.android.tv.TvSingletons;
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.data.ChannelDataManager;
+import com.android.tv.data.Program;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
 import com.android.tv.dvr.DvrDataManager.OnDvrScheduleLoadFinishedListener;
 import com.android.tv.dvr.DvrDataManager.ScheduledRecordingListener;
 import com.android.tv.dvr.data.ScheduledRecording;
@@ -38,7 +37,6 @@
 import com.android.tv.dvr.recorder.InputTaskScheduler;
 import com.android.tv.util.CompositeComparator;
 import com.android.tv.util.Utils;
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -78,7 +76,7 @@
                     ScheduledRecording.ID_COMPARATOR);
 
     private final Context mContext;
-    private final DvrDataManager mDataManager;
+    private final DvrDataManagerImpl mDataManager;
     private final ChannelDataManager mChannelDataManager;
 
     private final Map<String, List<ScheduledRecording>> mInputScheduleMap = new HashMap<>();
@@ -97,7 +95,7 @@
     public DvrScheduleManager(Context context) {
         mContext = context;
         TvSingletons tvSingletons = TvSingletons.getSingletons(context);
-        mDataManager = tvSingletons.getDvrDataManager();
+        mDataManager = (DvrDataManagerImpl) tvSingletons.getDvrDataManager();
         mChannelDataManager = tvSingletons.getChannelDataManager();
         if (mDataManager.isDvrScheduleLoadFinished() && mChannelDataManager.isDbLoadFinished()) {
             buildData();
diff --git a/src/com/android/tv/dvr/DvrStorageStatusManager.java b/src/com/android/tv/dvr/DvrStorageStatusManager.java
index a0ae893..dc347a9 100644
--- a/src/com/android/tv/dvr/DvrStorageStatusManager.java
+++ b/src/com/android/tv/dvr/DvrStorageStatusManager.java
@@ -114,7 +114,7 @@
                     return;
                 }
                 for (TvInputInfo info : tvInputInfoList) {
-                    if (CommonUtils.isBundledInput(info.getId()) && dvrManager != null) {
+                    if (CommonUtils.isBundledInput(info.getId())) {
                         dvrManager.forgetStorage(info.getId());
                     }
                 }
diff --git a/src/com/android/tv/dvr/DvrWatchedPositionManager.java b/src/com/android/tv/dvr/DvrWatchedPositionManager.java
index b4fea7f..8616962 100644
--- a/src/com/android/tv/dvr/DvrWatchedPositionManager.java
+++ b/src/com/android/tv/dvr/DvrWatchedPositionManager.java
@@ -20,10 +20,8 @@
 import android.content.SharedPreferences;
 import android.media.tv.TvInputManager;
 import android.support.annotation.IntDef;
-
 import com.android.tv.common.util.SharedPreferencesUtils;
 import com.android.tv.dvr.data.RecordedProgram;
-
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
@@ -38,7 +36,7 @@
  */
 public class DvrWatchedPositionManager {
     private SharedPreferences mWatchedPositions;
-    private final Map<Long, Set<WatchedPositionChangedListener>> mListeners = new HashMap<>();
+    private final Map<Long, Set> mListeners = new HashMap<>();
 
     /**
      * The minimum percentage of recorded program being watched that will be considered as being
diff --git a/src/com/android/tv/dvr/data/RecordedProgram.java b/src/com/android/tv/dvr/data/RecordedProgram.java
index 6143055..899e65a 100644
--- a/src/com/android/tv/dvr/data/RecordedProgram.java
+++ b/src/com/android/tv/dvr/data/RecordedProgram.java
@@ -36,10 +36,9 @@
 import com.android.tv.common.data.RecordedProgramState;
 import com.android.tv.common.util.CommonUtils;
 import com.android.tv.common.util.StringUtils;
-import com.android.tv.data.BaseProgramImpl;
+import com.android.tv.data.BaseProgram;
 import com.android.tv.data.GenreItems;
 import com.android.tv.data.InternalDataUtils;
-import com.android.tv.data.api.BaseProgram;
 import com.android.tv.util.TvProviderUtils;
 import com.google.auto.value.AutoValue;
 import com.google.common.collect.ImmutableList;
@@ -50,7 +49,7 @@
 /** Immutable instance of {@link android.media.tv.TvContract.RecordedPrograms}. */
 @TargetApi(Build.VERSION_CODES.N)
 @AutoValue
-public abstract class RecordedProgram extends BaseProgramImpl {
+public abstract class RecordedProgram extends BaseProgram {
     public static final int ID_NOT_SET = -1;
     private static final String TAG = "RecordedProgram";
 
diff --git a/src/com/android/tv/dvr/data/ScheduledRecording.java b/src/com/android/tv/dvr/data/ScheduledRecording.java
index 1237fb3..ba6d3cf 100644
--- a/src/com/android/tv/dvr/data/ScheduledRecording.java
+++ b/src/com/android/tv/dvr/data/ScheduledRecording.java
@@ -27,17 +27,15 @@
 import android.support.annotation.Nullable;
 import android.text.TextUtils;
 import android.util.Range;
-
 import com.android.tv.R;
 import com.android.tv.TvSingletons;
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.common.util.CommonUtils;
+import com.android.tv.data.Program;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
 import com.android.tv.dvr.DvrScheduleManager;
 import com.android.tv.dvr.provider.DvrContract.Schedules;
 import com.android.tv.util.CompositeComparator;
-
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.Collection;
@@ -494,7 +492,7 @@
                 }
             };
 
-    /** The ID internal to TV app */
+    /** The ID internal to Live TV */
     private long mId;
 
     /**
diff --git a/src/com/android/tv/dvr/data/SeriesRecording.java b/src/com/android/tv/dvr/data/SeriesRecording.java
index cd7d966..6cb0e83 100644
--- a/src/com/android/tv/dvr/data/SeriesRecording.java
+++ b/src/com/android/tv/dvr/data/SeriesRecording.java
@@ -22,14 +22,11 @@
 import android.os.Parcelable;
 import android.support.annotation.IntDef;
 import android.text.TextUtils;
-
-import com.android.tv.data.BaseProgramImpl;
-import com.android.tv.data.api.BaseProgram;
-import com.android.tv.data.api.Program;
+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;
-
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.Arrays;
@@ -88,8 +85,7 @@
             (SeriesRecording lhs, SeriesRecording rhs) -> Long.compare(lhs.mId, rhs.mId);
 
     /**
-     * Creates a new Builder with the values set from the series information of {@link
-     * BaseProgramImpl}.
+     * Creates a new Builder with the values set from the series information of {@link BaseProgram}.
      */
     public static Builder builder(String inputId, BaseProgram p) {
         return new Builder()
diff --git a/src/com/android/tv/dvr/provider/DvrContract.java b/src/com/android/tv/dvr/provider/DvrContract.java
index 8539ae3..a5f2e2c 100644
--- a/src/com/android/tv/dvr/provider/DvrContract.java
+++ b/src/com/android/tv/dvr/provider/DvrContract.java
@@ -20,7 +20,7 @@
 
 /**
  * The contract between the DVR provider and applications. Contains definitions for the supported
- * columns. It's for the internal use in TV app.
+ * columns. It's for the internal use in Live TV.
  */
 public final class DvrContract {
     /** Column definition for Schedules table. */
@@ -69,8 +69,8 @@
         public static final String FAILED_REASON_INVALID_CHANNEL = "FAILED_REASON_INVALID_CHANNEL";
 
         /** The recording failed because the scheduler was stopped */
-        public static final String FAILED_REASON_SCHEDULER_STOPPED =
-                "FAILED_REASON_SCHEDULER_STOPPED";
+        public static final String FAILED_REASON_SCHEDULER_STOPPED
+                = "FAILED_REASON_SCHEDULER_STOPPED";
 
         /** The recording failed because some messages were not sent to the message queue */
         public static final String FAILED_REASON_MESSAGE_NOT_SENT =
@@ -84,7 +84,8 @@
                 "FAILED_REASON_CONNECTION_FAILED";
 
         /**
-         * The recording failed because a required recording resource was not able to be allocated.
+         * The recording failed because a required recording resource was not able to be
+         * allocated.
          */
         public static final String FAILED_REASON_RESOURCE_BUSY = "FAILED_REASON_RESOURCE_BUSY";
 
diff --git a/src/com/android/tv/dvr/provider/DvrDatabaseHelper.java b/src/com/android/tv/dvr/provider/DvrDatabaseHelper.java
index 1dcda8e..ebf133d 100644
--- a/src/com/android/tv/dvr/provider/DvrDatabaseHelper.java
+++ b/src/com/android/tv/dvr/provider/DvrDatabaseHelper.java
@@ -26,18 +26,12 @@
 import android.provider.BaseColumns;
 import android.text.TextUtils;
 import android.util.Log;
-
-import com.android.tv.common.dagger.annotations.ApplicationContext;
 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 javax.inject.Inject;
-import javax.inject.Singleton;
-
 /** A data class for one recorded contents. */
-@Singleton
 public class DvrDatabaseHelper extends SQLiteOpenHelper {
     private static final String TAG = "DvrDatabaseHelper";
     private static final boolean DEBUG = false;
@@ -244,9 +238,8 @@
         return "DELETE FROM " + tableName + " WHERE " + BaseColumns._ID + "=?";
     }
 
-    @Inject
-    public DvrDatabaseHelper(@ApplicationContext Context context) {
-        super(context, DB_NAME, null, DATABASE_VERSION);
+    public DvrDatabaseHelper(Context context) {
+        super(context.getApplicationContext(), DB_NAME, null, DATABASE_VERSION);
     }
 
     @Override
@@ -273,12 +266,8 @@
             return;
         }
         if (oldVersion < 18) {
-            db.execSQL(
-                    "ALTER TABLE "
-                            + Schedules.TABLE_NAME
-                            + " ADD COLUMN "
-                            + Schedules.COLUMN_FAILED_REASON
-                            + " TEXT DEFAULT null;");
+            db.execSQL("ALTER TABLE " + Schedules.TABLE_NAME + " ADD COLUMN "
+                    + Schedules.COLUMN_FAILED_REASON + " TEXT DEFAULT null;");
         }
     }
 
diff --git a/src/com/android/tv/dvr/provider/DvrDbFuture.java b/src/com/android/tv/dvr/provider/DvrDbFuture.java
index cbc2c07..ae8c480 100644
--- a/src/com/android/tv/dvr/provider/DvrDbFuture.java
+++ b/src/com/android/tv/dvr/provider/DvrDbFuture.java
@@ -16,23 +16,21 @@
 
 package com.android.tv.dvr.provider;
 
+import android.content.Context;
 import android.database.Cursor;
 import android.support.annotation.Nullable;
 import android.util.Log;
-
 import com.android.tv.common.concurrent.NamedThreadFactory;
 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.MainThreadExecutor;
-
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.common.util.concurrent.MoreExecutors;
-
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.Executors;
@@ -40,24 +38,29 @@
 /** {@link DvrDbFuture} that defaults to executing on its own single threaded Executor Service. */
 public abstract class DvrDbFuture<ParamsT, ResultT> {
     private static final NamedThreadFactory THREAD_FACTORY =
-            new NamedThreadFactory(DvrDbFuture.class.getSimpleName());
+        new NamedThreadFactory(DvrDbFuture.class.getSimpleName());
     private static final ListeningExecutorService DB_EXECUTOR =
-            MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor(THREAD_FACTORY));
+        MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor(THREAD_FACTORY));
 
-    final DvrDatabaseHelper mDbHelper;
+    private static DvrDatabaseHelper sDbHelper;
     private ListenableFuture<ResultT> mFuture;
 
-    private DvrDbFuture(DvrDatabaseHelper mDbHelper) {
-        this.mDbHelper = mDbHelper;
+    final Context mContext;
+
+    private DvrDbFuture(Context context) {
+        mContext = context;
     }
 
-    /** Execute the task on the {@link #DB_EXECUTOR} thread and return Future */
+    /** Execute the task on the {@link #DB_EXECUTOR} thread and return Future*/
     @SafeVarargs
     public final ListenableFuture<ResultT> executeOnDbThread(
-            FutureCallback<ResultT> callback, ParamsT... params) {
-        mFuture = DB_EXECUTOR.submit(() -> dbHelperInBackground(params));
-        Futures.addCallback(mFuture, callback, MainThreadExecutor.getInstance());
-        return mFuture;
+        FutureCallback<ResultT> callback, ParamsT... params) {
+            if (sDbHelper == null) {
+                sDbHelper = new DvrDatabaseHelper(mContext.getApplicationContext());
+            }
+            mFuture = DB_EXECUTOR.submit(() -> dbHelperInBackground(params));
+            Futures.addCallback(mFuture, callback, MainThreadExecutor.getInstance());
+            return mFuture;
     }
 
     /** Executes in the background after initializing DbHelper} */
@@ -69,48 +72,52 @@
     }
 
     /** Inserts schedules. */
-    public static class AddScheduleFuture extends DvrDbFuture<ScheduledRecording, Void> {
-        public AddScheduleFuture(DvrDatabaseHelper dbHelper) {
-            super(dbHelper);
+    public static class AddScheduleFuture
+            extends DvrDbFuture<ScheduledRecording, Void> {
+        public AddScheduleFuture(Context context) {
+            super(context);
         }
 
         @Override
         protected final Void dbHelperInBackground(ScheduledRecording... params) {
-            mDbHelper.insertSchedules(params);
+            sDbHelper.insertSchedules(params);
             return null;
         }
     }
 
     /** Update schedules. */
-    public static class UpdateScheduleFuture extends DvrDbFuture<ScheduledRecording, Void> {
-        public UpdateScheduleFuture(DvrDatabaseHelper dbHelper) {
-            super(dbHelper);
+    public static class UpdateScheduleFuture
+            extends DvrDbFuture<ScheduledRecording, Void> {
+        public UpdateScheduleFuture(Context context) {
+            super(context);
         }
 
         @Override
         protected final Void dbHelperInBackground(ScheduledRecording... params) {
-            mDbHelper.updateSchedules(params);
+            sDbHelper.updateSchedules(params);
             return null;
         }
     }
 
     /** Delete schedules. */
-    public static class DeleteScheduleFuture extends DvrDbFuture<ScheduledRecording, Void> {
-        public DeleteScheduleFuture(DvrDatabaseHelper dbHelper) {
-            super(dbHelper);
+    public static class DeleteScheduleFuture
+            extends DvrDbFuture<ScheduledRecording, Void> {
+        public DeleteScheduleFuture(Context context) {
+            super(context);
         }
 
         @Override
         protected final Void dbHelperInBackground(ScheduledRecording... params) {
-            mDbHelper.deleteSchedules(params);
+            sDbHelper.deleteSchedules(params);
             return null;
         }
     }
 
     /** Returns all {@link ScheduledRecording}s. */
-    public static class DvrQueryScheduleFuture extends DvrDbFuture<Void, List<ScheduledRecording>> {
-        public DvrQueryScheduleFuture(DvrDatabaseHelper dbHelper) {
-            super(dbHelper);
+    public static class DvrQueryScheduleFuture
+            extends DvrDbFuture<Void, List<ScheduledRecording>> {
+        public DvrQueryScheduleFuture(Context context) {
+            super(context);
         }
 
         @Override
@@ -120,7 +127,7 @@
                 return null;
             }
             List<ScheduledRecording> scheduledRecordings = new ArrayList<>();
-            try (Cursor c = mDbHelper.query(Schedules.TABLE_NAME, ScheduledRecording.PROJECTION)) {
+            try (Cursor c = sDbHelper.query(Schedules.TABLE_NAME, ScheduledRecording.PROJECTION)) {
                 while (c.moveToNext() && !isCancelled()) {
                     scheduledRecordings.add(ScheduledRecording.fromCursor(c));
                 }
@@ -130,40 +137,43 @@
     }
 
     /** Inserts series recordings. */
-    public static class AddSeriesRecordingFuture extends DvrDbFuture<SeriesRecording, Void> {
-        public AddSeriesRecordingFuture(DvrDatabaseHelper dbHelper) {
-            super(dbHelper);
+    public static class AddSeriesRecordingFuture
+            extends DvrDbFuture<SeriesRecording, Void> {
+        public AddSeriesRecordingFuture(Context context) {
+            super(context);
         }
 
         @Override
         protected final Void dbHelperInBackground(SeriesRecording... params) {
-            mDbHelper.insertSeriesRecordings(params);
+            sDbHelper.insertSeriesRecordings(params);
             return null;
         }
     }
 
     /** Update series recordings. */
-    public static class UpdateSeriesRecordingFuture extends DvrDbFuture<SeriesRecording, Void> {
-        public UpdateSeriesRecordingFuture(DvrDatabaseHelper dbHelper) {
-            super(dbHelper);
+    public static class UpdateSeriesRecordingFuture
+            extends DvrDbFuture<SeriesRecording, Void> {
+        public UpdateSeriesRecordingFuture(Context context) {
+            super(context);
         }
 
         @Override
         protected final Void dbHelperInBackground(SeriesRecording... params) {
-            mDbHelper.updateSeriesRecordings(params);
+            sDbHelper.updateSeriesRecordings(params);
             return null;
         }
     }
 
     /** Delete series recordings. */
-    public static class DeleteSeriesRecordingFuture extends DvrDbFuture<SeriesRecording, Void> {
-        public DeleteSeriesRecordingFuture(DvrDatabaseHelper dbHelper) {
-            super(dbHelper);
+    public static class DeleteSeriesRecordingFuture
+            extends DvrDbFuture<SeriesRecording, Void> {
+        public DeleteSeriesRecordingFuture(Context context) {
+            super(context);
         }
 
         @Override
         protected final Void dbHelperInBackground(SeriesRecording... params) {
-            mDbHelper.deleteSeriesRecordings(params);
+            sDbHelper.deleteSeriesRecordings(params);
             return null;
         }
     }
@@ -173,8 +183,8 @@
             extends DvrDbFuture<Void, List<SeriesRecording>> {
         private static final String TAG = "DvrQuerySeriesRecording";
 
-        public DvrQuerySeriesRecordingFuture(DvrDatabaseHelper dbHelper) {
-            super(dbHelper);
+        public DvrQuerySeriesRecordingFuture(Context context) {
+            super(context);
         }
 
         @Override
@@ -185,7 +195,7 @@
             }
             List<SeriesRecording> scheduledRecordings = new ArrayList<>();
             try (Cursor c =
-                    mDbHelper.query(SeriesRecordings.TABLE_NAME, SeriesRecording.PROJECTION)) {
+                    sDbHelper.query(SeriesRecordings.TABLE_NAME, SeriesRecording.PROJECTION)) {
                 while (c.moveToNext() && !isCancelled()) {
                     scheduledRecordings.add(SeriesRecording.fromCursor(c));
                 }
diff --git a/src/com/android/tv/dvr/provider/DvrDbSync.java b/src/com/android/tv/dvr/provider/DvrDbSync.java
index c2eae77..7658ca4 100644
--- a/src/com/android/tv/dvr/provider/DvrDbSync.java
+++ b/src/com/android/tv/dvr/provider/DvrDbSync.java
@@ -29,19 +29,17 @@
 import android.support.annotation.MainThread;
 import android.support.annotation.VisibleForTesting;
 import android.util.Log;
-
 import com.android.tv.TvSingletons;
 import com.android.tv.data.ChannelDataManager;
-import com.android.tv.data.api.Program;
+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.WritableDvrDataManager;
 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.TvUriMatcher;
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashSet;
@@ -51,7 +49,6 @@
 import java.util.Queue;
 import java.util.Set;
 import java.util.concurrent.Executor;
-import java.util.concurrent.TimeUnit;
 
 /**
  * A class to synchronizes DVR DB with TvProvider.
@@ -68,11 +65,9 @@
     private static final String TAG = "DvrDbSync";
     private static final boolean DEBUG = false;
 
-    private static final long RECORD_MARGIN_MS = TimeUnit.SECONDS.toMillis(10);
-
     private final Context mContext;
     private final DvrManager mDvrManager;
-    private final WritableDvrDataManager mDataManager;
+    private final DvrDataManagerImpl mDataManager;
     private final ChannelDataManager mChannelDataManager;
     private final Executor mDbExecutor;
     private final Queue<Long> mProgramIdQueue = new LinkedList<>();
@@ -143,7 +138,7 @@
                 }
             };
 
-    public DvrDbSync(Context context, WritableDvrDataManager dataManager) {
+    public DvrDbSync(Context context, DvrDataManagerImpl dataManager) {
         this(
                 context,
                 dataManager,
@@ -156,7 +151,7 @@
     @VisibleForTesting
     DvrDbSync(
             Context context,
-            WritableDvrDataManager dataManager,
+            DvrDataManagerImpl dataManager,
             ChannelDataManager channelDataManager,
             DvrManager dvrManager,
             SeriesRecordingScheduler seriesRecordingScheduler,
@@ -330,15 +325,10 @@
                     // Old program belongs to a series but the new one doesn't.
                     seriesRecordingsToUpdate.add(seriesRecordingForOldSchedule);
                 }
-                // Change start time only when the recording is not started yet and if it is not
-                // within marginal time of current time. Marginal check is needed to prevent the
-                // update of start time if recording is just triggered or about to get triggered.
-                boolean marginalToCurrentTime = RECORD_MARGIN_MS >
-                        Math.abs(System.currentTimeMillis() - schedule.getStartTimeMs());
+                // Change start time only when the recording is not started yet.
                 boolean needToChangeStartTime =
                         schedule.getState() != ScheduledRecording.STATE_RECORDING_IN_PROGRESS
-                                && program.getStartTimeUtcMillis() != schedule.getStartTimeMs()
-                                && !marginalToCurrentTime;
+                                && program.getStartTimeUtcMillis() != schedule.getStartTimeMs();
                 if (needToChangeStartTime) {
                     builder.setStartTimeMs(program.getStartTimeUtcMillis());
                     needUpdate = true;
diff --git a/src/com/android/tv/dvr/provider/EpisodicProgramLoadTask.java b/src/com/android/tv/dvr/provider/EpisodicProgramLoadTask.java
index a66e5b0..02e197f 100644
--- a/src/com/android/tv/dvr/provider/EpisodicProgramLoadTask.java
+++ b/src/com/android/tv/dvr/provider/EpisodicProgramLoadTask.java
@@ -25,19 +25,16 @@
 import android.os.Build;
 import android.support.annotation.Nullable;
 import android.support.annotation.WorkerThread;
-
 import com.android.tv.TvSingletons;
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.common.util.PermissionUtils;
-import com.android.tv.data.ProgramImpl;
-import com.android.tv.data.api.Program;
+import com.android.tv.data.Program;
 import com.android.tv.dvr.DvrDataManager;
 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.util.AsyncDbTask.AsyncProgramQueryTask;
 import com.android.tv.util.AsyncDbTask.CursorFilter;
-
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -50,11 +47,11 @@
 public abstract class EpisodicProgramLoadTask {
     private static final String TAG = "EpisodicProgramLoadTask";
 
-    private static final int PROGRAM_ID_INDEX = ProgramImpl.getColumnIndex(Programs._ID);
+    private static final int PROGRAM_ID_INDEX = Program.getColumnIndex(Programs._ID);
     private static final int START_TIME_INDEX =
-            ProgramImpl.getColumnIndex(Programs.COLUMN_START_TIME_UTC_MILLIS);
+            Program.getColumnIndex(Programs.COLUMN_START_TIME_UTC_MILLIS);
     private static final int RECORDING_PROHIBITED_INDEX =
-            ProgramImpl.getColumnIndex(Programs.COLUMN_RECORDING_PROHIBITED);
+            Program.getColumnIndex(Programs.COLUMN_RECORDING_PROHIBITED);
 
     private static final String PARAM_START_TIME = "start_time";
     private static final String PARAM_END_TIME = "end_time";
@@ -292,7 +289,7 @@
                     && mDisallowedProgramIds.contains(c.getLong(PROGRAM_ID_INDEX))) {
                 return false;
             }
-            Program program = ProgramImpl.fromCursor(c);
+            Program program = Program.fromCursor(c);
             for (SeriesRecording seriesRecording : mSeriesRecordings) {
                 boolean programMatches;
                 if (mIgnoreChannelOption) {
diff --git a/src/com/android/tv/dvr/recorder/SeriesRecordingScheduler.java b/src/com/android/tv/dvr/recorder/SeriesRecordingScheduler.java
index 92b4e06..696038c 100644
--- a/src/com/android/tv/dvr/recorder/SeriesRecordingScheduler.java
+++ b/src/com/android/tv/dvr/recorder/SeriesRecordingScheduler.java
@@ -27,12 +27,11 @@
 import android.util.ArraySet;
 import android.util.Log;
 import android.util.LongSparseArray;
-
 import com.android.tv.TvSingletons;
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.common.util.CollectionUtils;
 import com.android.tv.common.util.SharedPreferencesUtils;
-import com.android.tv.data.api.Program;
+import com.android.tv.data.Program;
 import com.android.tv.data.epg.EpgReader;
 import com.android.tv.dvr.DvrDataManager;
 import com.android.tv.dvr.DvrDataManager.ScheduledRecordingListener;
@@ -44,9 +43,6 @@
 import com.android.tv.dvr.data.SeriesInfo;
 import com.android.tv.dvr.data.SeriesRecording;
 import com.android.tv.dvr.provider.EpisodicProgramLoadTask;
-
-import dagger.Lazy;
-
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -58,6 +54,7 @@
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
+import javax.inject.Provider;
 
 /**
  * Creates the {@link com.android.tv.dvr.data.ScheduledRecording}s for the {@link
@@ -532,9 +529,10 @@
 
     private class FetchSeriesInfoTask extends AsyncTask<Void, Void, SeriesInfo> {
         private final SeriesRecording mSeriesRecording;
-        private final Lazy<EpgReader> mEpgReaderProvider;
+        private final Provider<EpgReader> mEpgReaderProvider;
 
-        FetchSeriesInfoTask(SeriesRecording seriesRecording, Lazy<EpgReader> epgReaderProvider) {
+        FetchSeriesInfoTask(
+                SeriesRecording seriesRecording, Provider<EpgReader> epgReaderProvider) {
             mSeriesRecording = seriesRecording;
             mEpgReaderProvider = epgReaderProvider;
         }
diff --git a/src/com/android/tv/dvr/ui/DvrAlreadyRecordedFragment.java b/src/com/android/tv/dvr/ui/DvrAlreadyRecordedFragment.java
index 1f4faf3..5e3caa9 100644
--- a/src/com/android/tv/dvr/ui/DvrAlreadyRecordedFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrAlreadyRecordedFragment.java
@@ -22,16 +22,13 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.support.annotation.NonNull;
-
-import androidx.leanback.widget.GuidanceStylist.Guidance;
-import androidx.leanback.widget.GuidedAction;
-
+import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
+import android.support.v17.leanback.widget.GuidedAction;
 import com.android.tv.R;
 import com.android.tv.TvSingletons;
-import com.android.tv.data.api.Program;
+import com.android.tv.data.Program;
 import com.android.tv.dvr.DvrManager;
 import com.android.tv.dvr.data.RecordedProgram;
-
 import java.util.List;
 
 /**
diff --git a/src/com/android/tv/dvr/ui/DvrAlreadyScheduledFragment.java b/src/com/android/tv/dvr/ui/DvrAlreadyScheduledFragment.java
index 56ffc88..a6bbe13 100644
--- a/src/com/android/tv/dvr/ui/DvrAlreadyScheduledFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrAlreadyScheduledFragment.java
@@ -22,17 +22,14 @@
 import android.os.Build;
 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.format.DateUtils;
-
-import androidx.leanback.widget.GuidanceStylist.Guidance;
-import androidx.leanback.widget.GuidedAction;
-
 import com.android.tv.R;
 import com.android.tv.TvSingletons;
-import com.android.tv.data.api.Program;
+import com.android.tv.data.Program;
 import com.android.tv.dvr.DvrManager;
 import com.android.tv.dvr.data.ScheduledRecording;
-
 import java.util.List;
 
 /**
diff --git a/src/com/android/tv/dvr/ui/DvrChannelRecordDurationOptionFragment.java b/src/com/android/tv/dvr/ui/DvrChannelRecordDurationOptionFragment.java
index b24281a..6be35cb 100644
--- a/src/com/android/tv/dvr/ui/DvrChannelRecordDurationOptionFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrChannelRecordDurationOptionFragment.java
@@ -18,9 +18,9 @@
 
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
-import androidx.leanback.app.GuidedStepFragment;
-import androidx.leanback.widget.GuidanceStylist.Guidance;
-import androidx.leanback.widget.GuidedAction;
+import android.support.v17.leanback.app.GuidedStepFragment;
+import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
+import android.support.v17.leanback.widget.GuidedAction;
 import com.android.tv.R;
 import com.android.tv.TvSingletons;
 import com.android.tv.common.SoftPreconditions;
diff --git a/src/com/android/tv/dvr/ui/DvrConflictFragment.java b/src/com/android/tv/dvr/ui/DvrConflictFragment.java
index 5e0a96b..649cc89 100644
--- a/src/com/android/tv/dvr/ui/DvrConflictFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrConflictFragment.java
@@ -21,25 +21,22 @@
 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.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-
-import androidx.leanback.widget.GuidanceStylist.Guidance;
-import androidx.leanback.widget.GuidedAction;
-
 import com.android.tv.MainActivity;
 import com.android.tv.R;
 import com.android.tv.TvSingletons;
 import com.android.tv.common.SoftPreconditions;
+import com.android.tv.data.Program;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
 import com.android.tv.dvr.data.ScheduledRecording;
 import com.android.tv.dvr.recorder.ConflictChecker;
 import com.android.tv.dvr.recorder.ConflictChecker.OnUpcomingConflictChangeListener;
 import com.android.tv.util.Utils;
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashSet;
diff --git a/src/com/android/tv/dvr/ui/DvrGuidedActionsStylist.java b/src/com/android/tv/dvr/ui/DvrGuidedActionsStylist.java
index 81fc3ed..611962d 100644
--- a/src/com/android/tv/dvr/ui/DvrGuidedActionsStylist.java
+++ b/src/com/android/tv/dvr/ui/DvrGuidedActionsStylist.java
@@ -17,8 +17,8 @@
 package com.android.tv.dvr.ui;
 
 import android.content.Context;
-import androidx.leanback.app.GuidedStepFragment;
-import androidx.leanback.widget.GuidedActionsStylist;
+import android.support.v17.leanback.app.GuidedStepFragment;
+import android.support.v17.leanback.widget.GuidedActionsStylist;
 import android.util.TypedValue;
 import android.view.LayoutInflater;
 import android.view.View;
diff --git a/src/com/android/tv/dvr/ui/DvrGuidedStepFragment.java b/src/com/android/tv/dvr/ui/DvrGuidedStepFragment.java
index fda4cde..a900cc7 100644
--- a/src/com/android/tv/dvr/ui/DvrGuidedStepFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrGuidedStepFragment.java
@@ -20,9 +20,9 @@
 import android.app.DialogFragment;
 import android.content.Context;
 import android.os.Bundle;
-import androidx.leanback.widget.GuidanceStylist;
-import androidx.leanback.widget.GuidedAction;
-import androidx.leanback.widget.VerticalGridView;
+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;
diff --git a/src/com/android/tv/dvr/ui/DvrHalfSizedDialogFragment.java b/src/com/android/tv/dvr/ui/DvrHalfSizedDialogFragment.java
index e8f501e..e6b54f6 100644
--- a/src/com/android/tv/dvr/ui/DvrHalfSizedDialogFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrHalfSizedDialogFragment.java
@@ -20,15 +20,13 @@
 import android.content.Context;
 import android.content.DialogInterface;
 import android.os.Bundle;
+import android.support.v17.leanback.app.GuidedStepFragment;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
-import androidx.leanback.app.GuidedStepFragment;
-
 import com.android.tv.MainActivity;
 import com.android.tv.R;
-import com.android.tv.data.ProgramImpl;
 import com.android.tv.dialog.HalfSizedDialogFragment;
 import com.android.tv.dvr.ui.DvrConflictFragment.DvrChannelWatchConflictFragment;
 import com.android.tv.dvr.ui.DvrConflictFragment.DvrProgramConflictFragment;
@@ -38,7 +36,7 @@
 public class DvrHalfSizedDialogFragment extends HalfSizedDialogFragment {
     /** Key for input ID. Type: String. */
     public static final String KEY_INPUT_ID = "DvrHalfSizedDialogFragment.input_id";
-    /** Key for the program. Type: {@link ProgramImpl}. */
+    /** Key for the program. Type: {@link com.android.tv.data.Program}. */
     public static final String KEY_PROGRAM = "DvrHalfSizedDialogFragment.program";
     /** Key for the channel ID. Type: long. */
     public static final String KEY_CHANNEL_ID = "DvrHalfSizedDialogFragment.channel_id";
diff --git a/src/com/android/tv/dvr/ui/DvrInsufficientSpaceErrorFragment.java b/src/com/android/tv/dvr/ui/DvrInsufficientSpaceErrorFragment.java
index 01631b9..6fba4d9 100644
--- a/src/com/android/tv/dvr/ui/DvrInsufficientSpaceErrorFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrInsufficientSpaceErrorFragment.java
@@ -20,8 +20,8 @@
 import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
-import androidx.leanback.widget.GuidanceStylist.Guidance;
-import androidx.leanback.widget.GuidedAction;
+import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
+import android.support.v17.leanback.widget.GuidedAction;
 import com.android.tv.R;
 import com.android.tv.TvSingletons;
 import com.android.tv.common.SoftPreconditions;
diff --git a/src/com/android/tv/dvr/ui/DvrMissingStorageErrorFragment.java b/src/com/android/tv/dvr/ui/DvrMissingStorageErrorFragment.java
index 3237acd..02b2da1 100644
--- a/src/com/android/tv/dvr/ui/DvrMissingStorageErrorFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrMissingStorageErrorFragment.java
@@ -21,8 +21,8 @@
 import android.content.Intent;
 import android.os.Bundle;
 import android.provider.Settings;
-import androidx.leanback.widget.GuidanceStylist.Guidance;
-import androidx.leanback.widget.GuidedAction;
+import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
+import android.support.v17.leanback.widget.GuidedAction;
 import android.util.Log;
 import com.android.tv.R;
 import com.android.tv.ui.DetailsActivity;
diff --git a/src/com/android/tv/dvr/ui/DvrPrioritySettingsFragment.java b/src/com/android/tv/dvr/ui/DvrPrioritySettingsFragment.java
index ae41f50..5bb97e9 100644
--- a/src/com/android/tv/dvr/ui/DvrPrioritySettingsFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrPrioritySettingsFragment.java
@@ -22,9 +22,9 @@
 import android.graphics.Typeface;
 import android.os.Build;
 import android.os.Bundle;
-import androidx.leanback.widget.GuidanceStylist.Guidance;
-import androidx.leanback.widget.GuidedAction;
-import androidx.leanback.widget.GuidedActionsStylist;
+import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
+import android.support.v17.leanback.widget.GuidedAction;
+import android.support.v17.leanback.widget.GuidedActionsStylist;
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.TextView;
diff --git a/src/com/android/tv/dvr/ui/DvrScheduleFragment.java b/src/com/android/tv/dvr/ui/DvrScheduleFragment.java
index 7131f62..72603d0 100644
--- a/src/com/android/tv/dvr/ui/DvrScheduleFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrScheduleFragment.java
@@ -22,21 +22,18 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.support.annotation.NonNull;
+import android.support.v17.leanback.app.GuidedStepFragment;
+import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
+import android.support.v17.leanback.widget.GuidedAction;
 import android.text.format.DateUtils;
-
-import androidx.leanback.app.GuidedStepFragment;
-import androidx.leanback.widget.GuidanceStylist.Guidance;
-import androidx.leanback.widget.GuidedAction;
-
 import com.android.tv.R;
 import com.android.tv.TvSingletons;
 import com.android.tv.common.SoftPreconditions;
-import com.android.tv.data.ProgramImpl;
+import com.android.tv.data.Program;
 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.ui.DvrConflictFragment.DvrProgramConflictFragment;
-
 import java.util.Collections;
 import java.util.List;
 
@@ -55,7 +52,7 @@
     private static final int ACTION_RECORD_EPISODE = 1;
     private static final int ACTION_RECORD_SERIES = 2;
 
-    private ProgramImpl mProgram;
+    private Program mProgram;
     private boolean mAddCurrentProgramToSeries;
 
     @Override
diff --git a/src/com/android/tv/dvr/ui/DvrSeriesDeletionActivity.java b/src/com/android/tv/dvr/ui/DvrSeriesDeletionActivity.java
index 730237c..a237f1d 100644
--- a/src/com/android/tv/dvr/ui/DvrSeriesDeletionActivity.java
+++ b/src/com/android/tv/dvr/ui/DvrSeriesDeletionActivity.java
@@ -20,13 +20,15 @@
 import android.content.pm.PackageManager;
 import android.os.Bundle;
 import android.support.annotation.NonNull;
-import androidx.leanback.app.GuidedStepFragment;
+import android.support.v17.leanback.app.GuidedStepFragment;
 import android.util.Log;
 import android.widget.Toast;
+
 import com.android.tv.R;
 import com.android.tv.Starter;
 import com.android.tv.TvSingletons;
 import com.android.tv.dvr.DvrManager;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -68,7 +70,7 @@
                         && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                     deleteSelectedIds(true);
                 } else {
-                    // NOTE: If TV app ever supports both embedded and separate DVR inputs
+                    // NOTE: If Live TV ever supports both embedded and separate DVR inputs
                     // then we should try to do the delete regardless.
                     Log.i(
                             TAG,
@@ -91,14 +93,14 @@
             dvrManager.removeRecordedPrograms(mIdsToDelete, deleteFiles);
         }
         Toast.makeText(
-                        this,
-                        getResources()
-                                .getQuantityString(
-                                        R.plurals.dvr_msg_episodes_deleted,
-                                        mIdsToDelete.size(),
-                                        mIdsToDelete.size(),
-                                        recordingSize),
-                        Toast.LENGTH_LONG)
+                this,
+                getResources()
+                        .getQuantityString(
+                                R.plurals.dvr_msg_episodes_deleted,
+                                mIdsToDelete.size(),
+                                mIdsToDelete.size(),
+                                recordingSize),
+                Toast.LENGTH_LONG)
                 .show();
         finish();
     }
diff --git a/src/com/android/tv/dvr/ui/DvrSeriesDeletionFragment.java b/src/com/android/tv/dvr/ui/DvrSeriesDeletionFragment.java
index 10ef226..ff21323 100644
--- a/src/com/android/tv/dvr/ui/DvrSeriesDeletionFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrSeriesDeletionFragment.java
@@ -19,10 +19,10 @@
 import android.content.Context;
 import android.media.tv.TvInputManager;
 import android.os.Bundle;
-import androidx.leanback.app.GuidedStepFragment;
-import androidx.leanback.widget.GuidanceStylist.Guidance;
-import androidx.leanback.widget.GuidedAction;
-import androidx.leanback.widget.GuidedActionsStylist;
+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.text.TextUtils;
 import android.view.ViewGroup.LayoutParams;
 import android.widget.Toast;
diff --git a/src/com/android/tv/dvr/ui/DvrSeriesScheduledDialogActivity.java b/src/com/android/tv/dvr/ui/DvrSeriesScheduledDialogActivity.java
index d72099b..9acb5b5 100644
--- a/src/com/android/tv/dvr/ui/DvrSeriesScheduledDialogActivity.java
+++ b/src/com/android/tv/dvr/ui/DvrSeriesScheduledDialogActivity.java
@@ -18,7 +18,7 @@
 
 import android.app.Activity;
 import android.os.Bundle;
-import androidx.leanback.app.GuidedStepFragment;
+import android.support.v17.leanback.app.GuidedStepFragment;
 import com.android.tv.R;
 
 public class DvrSeriesScheduledDialogActivity extends Activity {
diff --git a/src/com/android/tv/dvr/ui/DvrSeriesScheduledFragment.java b/src/com/android/tv/dvr/ui/DvrSeriesScheduledFragment.java
index 7d36990..c6e2685 100644
--- a/src/com/android/tv/dvr/ui/DvrSeriesScheduledFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrSeriesScheduledFragment.java
@@ -20,26 +20,22 @@
 import android.content.Intent;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
-
-import androidx.leanback.widget.GuidanceStylist;
-import androidx.leanback.widget.GuidedAction;
-
+import android.support.v17.leanback.widget.GuidanceStylist;
+import android.support.v17.leanback.widget.GuidedAction;
 import com.android.tv.R;
 import com.android.tv.TvSingletons;
-import com.android.tv.data.ProgramImpl;
-import com.android.tv.data.api.Program;
+import com.android.tv.data.Program;
 import com.android.tv.dvr.DvrScheduleManager;
 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 ProgramImpl}>
+     * List<{@link Program}>
      */
     public static final String SERIES_SCHEDULED_KEY_PROGRAMS = "series_scheduled_key_programs";
 
@@ -50,7 +46,6 @@
     private SeriesRecording mSeriesRecording;
     private boolean mShowViewScheduleOption;
     private List<Program> mPrograms;
-    private String mSeriesRecordingTitle;
 
     private int mSchedulesAddedCount = 0;
     private boolean mHasConflict = false;
@@ -80,7 +75,6 @@
             getActivity().finish();
             return;
         }
-        mSeriesRecordingTitle = mSeriesRecording.getTitle();
         mPrograms = (List<Program>) BigArguments.getArgument(SERIES_SCHEDULED_KEY_PROGRAMS);
         BigArguments.reset();
         mSchedulesAddedCount =
@@ -168,7 +162,7 @@
                             R.plurals.dvr_series_scheduled_no_conflict,
                             mSchedulesAddedCount,
                             mSchedulesAddedCount,
-                            mSeriesRecordingTitle);
+                            mSeriesRecording.getTitle());
         } else {
             // mInThisSeriesConflictCount equals 0 and mOutThisSeriesConflictCount equals 0 means
             // mHasConflict is false. So we don't need to check that case.
@@ -178,7 +172,7 @@
                                 R.plurals.dvr_series_scheduled_this_and_other_series_conflict,
                                 mSchedulesAddedCount,
                                 mSchedulesAddedCount,
-                                mSeriesRecordingTitle,
+                                mSeriesRecording.getTitle(),
                                 mInThisSeriesConflictCount + mOutThisSeriesConflictCount);
             } else if (mInThisSeriesConflictCount != 0) {
                 return getResources()
@@ -186,7 +180,7 @@
                                 R.plurals.dvr_series_recording_scheduled_only_this_series_conflict,
                                 mSchedulesAddedCount,
                                 mSchedulesAddedCount,
-                                mSeriesRecordingTitle,
+                                mSeriesRecording.getTitle(),
                                 mInThisSeriesConflictCount);
             } else {
                 if (mOutThisSeriesConflictCount == 1) {
@@ -195,14 +189,14 @@
                                     R.plurals.dvr_series_scheduled_only_other_series_one_conflict,
                                     mSchedulesAddedCount,
                                     mSchedulesAddedCount,
-                                    mSeriesRecordingTitle);
+                                    mSeriesRecording.getTitle());
                 } else {
                     return getResources()
                             .getQuantityString(
                                     R.plurals.dvr_series_scheduled_only_other_series_many_conflicts,
                                     mSchedulesAddedCount,
                                     mSchedulesAddedCount,
-                                    mSeriesRecordingTitle,
+                                    mSeriesRecording.getTitle(),
                                     mOutThisSeriesConflictCount);
                 }
             }
diff --git a/src/com/android/tv/dvr/ui/DvrSeriesSettingsActivity.java b/src/com/android/tv/dvr/ui/DvrSeriesSettingsActivity.java
index eb3ca28..1a51cf4 100644
--- a/src/com/android/tv/dvr/ui/DvrSeriesSettingsActivity.java
+++ b/src/com/android/tv/dvr/ui/DvrSeriesSettingsActivity.java
@@ -19,13 +19,10 @@
 import android.app.Activity;
 import android.graphics.drawable.ColorDrawable;
 import android.os.Bundle;
-
-import androidx.leanback.app.GuidedStepFragment;
-
+import android.support.v17.leanback.app.GuidedStepFragment;
 import com.android.tv.R;
 import com.android.tv.Starter;
 import com.android.tv.common.SoftPreconditions;
-import com.android.tv.data.ProgramImpl;
 
 /** Activity to show details view in DVR. */
 public class DvrSeriesSettingsActivity extends Activity {
@@ -43,7 +40,7 @@
     public static final String IS_WINDOW_TRANSLUCENT = "windows_translucent";
     /**
      * Name of the program list. The list contains the programs which belong to the series. Type:
-     * List<{@link ProgramImpl}>
+     * List<{@link com.android.tv.data.Program}>
      */
     public static final String PROGRAM_LIST = "program_list";
 
diff --git a/src/com/android/tv/dvr/ui/DvrSeriesSettingsFragment.java b/src/com/android/tv/dvr/ui/DvrSeriesSettingsFragment.java
index 7fc201c..eadb3b9 100644
--- a/src/com/android/tv/dvr/ui/DvrSeriesSettingsFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrSeriesSettingsFragment.java
@@ -21,19 +21,17 @@
 import android.content.Context;
 import android.os.Build;
 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.LongSparseArray;
-
-import androidx.leanback.app.GuidedStepFragment;
-import androidx.leanback.widget.GuidanceStylist.Guidance;
-import androidx.leanback.widget.GuidedAction;
-import androidx.leanback.widget.GuidedActionsStylist;
-
 import com.android.tv.R;
 import com.android.tv.TvSingletons;
 import com.android.tv.data.ChannelDataManager;
 import com.android.tv.data.ChannelImpl;
+import com.android.tv.data.Program;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
 import com.android.tv.dvr.DvrDataManager;
 import com.android.tv.dvr.DvrManager;
 import com.android.tv.dvr.data.ScheduledRecording;
@@ -41,7 +39,6 @@
 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.Collections;
 import java.util.HashSet;
@@ -72,7 +69,6 @@
     private Program mCurrentProgram;
 
     private String mFragmentTitle;
-    private String mSeriesRecordingTitle;
     private String mProrityActionTitle;
     private String mProrityActionHighestText;
     private String mProrityActionLowestText;
@@ -96,7 +92,6 @@
             getActivity().finish();
             return;
         }
-        mSeriesRecordingTitle = mSeriesRecording.getTitle();
         mShowViewScheduleOptionInDialog =
                 getArguments()
                         .getBoolean(DvrSeriesSettingsActivity.SHOW_VIEW_SCHEDULE_OPTION_IN_DIALOG);
@@ -166,8 +161,9 @@
 
     @Override
     public Guidance onCreateGuidance(Bundle savedInstanceState) {
+        String breadcrumb = mSeriesRecording.getTitle();
         String title = mFragmentTitle;
-        return new Guidance(title, null, mSeriesRecordingTitle, null);
+        return new Guidance(title, null, breadcrumb, null);
     }
 
     @Override
diff --git a/src/com/android/tv/dvr/ui/DvrStopRecordingFragment.java b/src/com/android/tv/dvr/ui/DvrStopRecordingFragment.java
index 1475a8c..1ab4c50 100644
--- a/src/com/android/tv/dvr/ui/DvrStopRecordingFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrStopRecordingFragment.java
@@ -23,17 +23,13 @@
 import android.os.Bundle;
 import android.support.annotation.IntDef;
 import android.support.annotation.NonNull;
-
-import androidx.leanback.widget.GuidanceStylist.Guidance;
-import androidx.leanback.widget.GuidedAction;
-
+import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
+import android.support.v17.leanback.widget.GuidedAction;
 import com.android.tv.R;
 import com.android.tv.TvSingletons;
-import com.android.tv.data.ProgramImpl;
 import com.android.tv.dvr.DvrDataManager;
 import com.android.tv.dvr.DvrDataManager.ScheduledRecordingListener;
 import com.android.tv.dvr.data.ScheduledRecording;
-
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.List;
@@ -48,7 +44,7 @@
 public class DvrStopRecordingFragment extends DvrGuidedStepFragment {
     /** The action ID for the stop action. */
     public static final int ACTION_STOP = 1;
-    /** Key for the program. Type: {@link ProgramImpl}. */
+    /** Key for the program. Type: {@link com.android.tv.data.Program}. */
     public static final String KEY_REASON = "DvrStopRecordingFragment.type";
 
     @Retention(RetentionPolicy.SOURCE)
diff --git a/src/com/android/tv/dvr/ui/DvrStopSeriesRecordingDialogFragment.java b/src/com/android/tv/dvr/ui/DvrStopSeriesRecordingDialogFragment.java
index 4a8ce04..15abf90 100644
--- a/src/com/android/tv/dvr/ui/DvrStopSeriesRecordingDialogFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrStopSeriesRecordingDialogFragment.java
@@ -18,7 +18,7 @@
 
 import android.app.DialogFragment;
 import android.os.Bundle;
-import androidx.leanback.app.GuidedStepFragment;
+import android.support.v17.leanback.app.GuidedStepFragment;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
diff --git a/src/com/android/tv/dvr/ui/DvrStopSeriesRecordingFragment.java b/src/com/android/tv/dvr/ui/DvrStopSeriesRecordingFragment.java
index 0b8f5df..99211fd 100644
--- a/src/com/android/tv/dvr/ui/DvrStopSeriesRecordingFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrStopSeriesRecordingFragment.java
@@ -20,8 +20,8 @@
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.support.annotation.NonNull;
-import androidx.leanback.widget.GuidanceStylist;
-import androidx.leanback.widget.GuidedAction;
+import android.support.v17.leanback.widget.GuidanceStylist;
+import android.support.v17.leanback.widget.GuidedAction;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
diff --git a/src/com/android/tv/dvr/ui/DvrUiHelper.java b/src/com/android/tv/dvr/ui/DvrUiHelper.java
index 657abfa..a121cf9 100644
--- a/src/com/android/tv/dvr/ui/DvrUiHelper.java
+++ b/src/com/android/tv/dvr/ui/DvrUiHelper.java
@@ -33,7 +33,6 @@
 import android.text.Spannable;
 import android.text.SpannableString;
 import android.text.SpannableStringBuilder;
-import android.text.Spanned;
 import android.text.TextUtils;
 import android.text.style.TextAppearanceSpan;
 import android.widget.ImageView;
@@ -45,9 +44,9 @@
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.common.recording.RecordingStorageStatusManager;
 import com.android.tv.common.util.CommonUtils;
-import com.android.tv.data.api.BaseProgram;
+import com.android.tv.data.BaseProgram;
+import com.android.tv.data.Program;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
 import com.android.tv.dialog.HalfSizedDialogFragment;
 import com.android.tv.dvr.DvrManager;
 import com.android.tv.dvr.data.RecordedProgram;
@@ -76,7 +75,6 @@
 import com.android.tv.util.ToastUtils;
 import com.android.tv.util.Utils;
 
-import com.google.common.collect.ImmutableList;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -124,7 +122,7 @@
             return;
         }
         Bundle args = new Bundle();
-        args.putParcelable(DvrHalfSizedDialogFragment.KEY_PROGRAM, program.toParcelable());
+        args.putParcelable(DvrHalfSizedDialogFragment.KEY_PROGRAM, program);
         args.putBoolean(
                 DvrScheduleFragment.KEY_ADD_CURRENT_PROGRAM_TO_SERIES, addCurrentProgramToSeries);
         showDialogFragment(activity, new DvrScheduleDialogFragment(), args, true, true);
@@ -146,7 +144,7 @@
             return;
         }
         Bundle args = new Bundle();
-        args.putParcelable(DvrHalfSizedDialogFragment.KEY_PROGRAM, program.toParcelable());
+        args.putParcelable(DvrHalfSizedDialogFragment.KEY_PROGRAM, program);
         showDialogFragment(activity, new DvrProgramConflictDialogFragment(), args, false, true);
     }
 
@@ -229,7 +227,7 @@
             return;
         }
         Bundle args = new Bundle();
-        args.putParcelable(DvrHalfSizedDialogFragment.KEY_PROGRAM, program.toParcelable());
+        args.putParcelable(DvrHalfSizedDialogFragment.KEY_PROGRAM, program);
         showDialogFragment(activity, new DvrAlreadyScheduledDialogFragment(), args, false, true);
     }
 
@@ -239,18 +237,14 @@
             return;
         }
         Bundle args = new Bundle();
-        args.putParcelable(DvrHalfSizedDialogFragment.KEY_PROGRAM, program.toParcelable());
+        args.putParcelable(DvrHalfSizedDialogFragment.KEY_PROGRAM, program);
         showDialogFragment(activity, new DvrAlreadyRecordedDialogFragment(), args, false, true);
     }
 
     /** Shows program information dialog. */
     public static void showWriteStoragePermissionRationaleDialog(Activity activity) {
-        showDialogFragment(
-                activity,
-                new DvrWriteStoragePermissionRationaleDialogFragment(),
-                new Bundle(),
-                false,
-                false);
+        showDialogFragment(activity, new DvrWriteStoragePermissionRationaleDialogFragment(),
+                new Bundle(), false, false);
     }
 
     /**
@@ -465,7 +459,7 @@
             boolean removeEmptySeriesSchedule,
             boolean isWindowTranslucent,
             boolean showViewScheduleOptionInDialog,
-            @Nullable Program currentProgram) {
+            Program currentProgram) {
         SeriesRecording series =
                 TvSingletons.getSingletons(context)
                         .getDvrDataManager()
@@ -487,15 +481,13 @@
                     new EpisodicProgramLoadTask(context, series) {
                         @Override
                         protected void onPostExecute(List<Program> loadedPrograms) {
-                            if (sProgressDialog != null) {
-                                sProgressDialog.dismiss();
-                                sProgressDialog = null;
-                            }
+                            sProgressDialog.dismiss();
+                            sProgressDialog = null;
                             startSeriesSettingsActivityInternal(
                                     context,
                                     seriesRecordingId,
                                     loadedPrograms == null
-                                            ? ImmutableList.of()
+                                            ? Collections.EMPTY_LIST
                                             : loadedPrograms,
                                     removeEmptySeriesSchedule,
                                     isWindowTranslucent,
@@ -532,7 +524,7 @@
             boolean removeEmptySeriesSchedule,
             boolean isWindowTranslucent,
             boolean showViewScheduleOptionInDialog,
-            @Nullable Program currentProgram) {
+            Program currentProgram) {
         SoftPreconditions.checkState(
                 programs != null, TAG, "Start series settings activity but programs is null");
         Intent intent = new Intent(context, DvrSeriesSettingsActivity.class);
@@ -545,9 +537,7 @@
         intent.putExtra(
                 DvrSeriesSettingsActivity.SHOW_VIEW_SCHEDULE_OPTION_IN_DIALOG,
                 showViewScheduleOptionInDialog);
-        if (currentProgram != null) {
-            intent.putExtra(DvrSeriesSettingsActivity.CURRENT_PROGRAM, currentProgram.toParcelable());
-        }
+        intent.putExtra(DvrSeriesSettingsActivity.CURRENT_PROGRAM, currentProgram);
         context.startActivity(intent);
     }
 
@@ -692,18 +682,16 @@
         }
         SpannableStringBuilder builder;
         if (TextUtils.isEmpty(seasonNumber) || seasonNumber.equals("0")) {
-            Spanned temp =
+            builder =
                     TextUtils.isEmpty(episodeNumber)
-                            ? SpannableStringBuilder.valueOf(title)
-                            : Html.fromHtml(
-                                    context.getString(
-                                            R.string.program_title_with_episode_number_no_season,
-                                            title,
-                                            episodeNumber));
-            builder = SpannableStringBuilder.valueOf(temp);
+                            ? new SpannableStringBuilder(title)
+                            : new SpannableStringBuilder(Html.fromHtml(context.getString(
+                                    R.string.program_title_with_episode_number_no_season,
+                                    title,
+                                    episodeNumber)));
         } else {
             builder =
-                    SpannableStringBuilder.valueOf(
+                    new SpannableStringBuilder(
                             Html.fromHtml(
                                     context.getString(
                                             R.string.program_title_with_episode_number,
diff --git a/src/com/android/tv/dvr/ui/DvrWriteStoragePermissionRationaleFragment.java b/src/com/android/tv/dvr/ui/DvrWriteStoragePermissionRationaleFragment.java
index 25f7f38..c93f583 100644
--- a/src/com/android/tv/dvr/ui/DvrWriteStoragePermissionRationaleFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrWriteStoragePermissionRationaleFragment.java
@@ -19,8 +19,8 @@
 import android.app.Activity;
 import android.content.res.Resources;
 import android.os.Bundle;
-import androidx.leanback.widget.GuidanceStylist;
-import androidx.leanback.widget.GuidedAction;
+import android.support.v17.leanback.widget.GuidanceStylist;
+import android.support.v17.leanback.widget.GuidedAction;
 
 import com.android.tv.R;
 
diff --git a/src/com/android/tv/dvr/ui/SortedArrayAdapter.java b/src/com/android/tv/dvr/ui/SortedArrayAdapter.java
index 7a26d5e..1eb8080 100644
--- a/src/com/android/tv/dvr/ui/SortedArrayAdapter.java
+++ b/src/com/android/tv/dvr/ui/SortedArrayAdapter.java
@@ -17,8 +17,8 @@
 package com.android.tv.dvr.ui;
 
 import android.support.annotation.VisibleForTesting;
-import androidx.leanback.widget.ArrayObjectAdapter;
-import androidx.leanback.widget.PresenterSelector;
+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;
diff --git a/src/com/android/tv/dvr/ui/TrackedGuidedStepFragment.java b/src/com/android/tv/dvr/ui/TrackedGuidedStepFragment.java
index c0a57c0..0172f76 100644
--- a/src/com/android/tv/dvr/ui/TrackedGuidedStepFragment.java
+++ b/src/com/android/tv/dvr/ui/TrackedGuidedStepFragment.java
@@ -17,8 +17,8 @@
 package com.android.tv.dvr.ui;
 
 import android.content.Context;
-import androidx.leanback.app.GuidedStepFragment;
-import androidx.leanback.widget.GuidedAction;
+import android.support.v17.leanback.app.GuidedStepFragment;
+import android.support.v17.leanback.widget.GuidedAction;
 import com.android.tv.TvSingletons;
 import com.android.tv.analytics.Tracker;
 
diff --git a/src/com/android/tv/dvr/ui/browse/ActionPresenterSelector.java b/src/com/android/tv/dvr/ui/browse/ActionPresenterSelector.java
index a06705c..41ace9a 100644
--- a/src/com/android/tv/dvr/ui/browse/ActionPresenterSelector.java
+++ b/src/com/android/tv/dvr/ui/browse/ActionPresenterSelector.java
@@ -17,10 +17,10 @@
 package com.android.tv.dvr.ui.browse;
 
 import android.graphics.drawable.Drawable;
-import androidx.leanback.R;
-import androidx.leanback.widget.Action;
-import androidx.leanback.widget.Presenter;
-import androidx.leanback.widget.PresenterSelector;
+import android.support.v17.leanback.R;
+import android.support.v17.leanback.widget.Action;
+import android.support.v17.leanback.widget.Presenter;
+import android.support.v17.leanback.widget.PresenterSelector;
 import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.View;
diff --git a/src/com/android/tv/dvr/ui/browse/CurrentRecordingDetailsFragment.java b/src/com/android/tv/dvr/ui/browse/CurrentRecordingDetailsFragment.java
index 88ef112..8c311d6 100644
--- a/src/com/android/tv/dvr/ui/browse/CurrentRecordingDetailsFragment.java
+++ b/src/com/android/tv/dvr/ui/browse/CurrentRecordingDetailsFragment.java
@@ -19,13 +19,12 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.media.tv.TvInputManager;
-
-import androidx.leanback.widget.Action;
-import androidx.leanback.widget.OnActionClickedListener;
-import androidx.leanback.widget.SparseArrayObjectAdapter;
-
+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.TvSingletons;
+import com.android.tv.common.flags.has.HasConcurrentDvrPlaybackFlags;
 import com.android.tv.dialog.HalfSizedDialogFragment;
 import com.android.tv.dvr.DvrDataManager;
 import com.android.tv.dvr.DvrManager;
@@ -34,10 +33,7 @@
 import com.android.tv.dvr.data.ScheduledRecording;
 import com.android.tv.dvr.ui.DvrStopRecordingFragment;
 import com.android.tv.dvr.ui.DvrUiHelper;
-
-import dagger.android.AndroidInjection;
-
-import javax.inject.Inject;
+import com.android.tv.common.flags.ConcurrentDvrPlaybackFlags;
 
 /** {@link RecordingDetailsFragment} for current recording in DVR. */
 public class CurrentRecordingDetailsFragment extends RecordingDetailsFragment {
@@ -47,7 +43,8 @@
 
     private DvrDataManager mDvrDataManger;
     private RecordedProgram mRecordedProgram;
-    @Inject DvrWatchedPositionManager mDvrWatchedPositionManager;
+    private DvrWatchedPositionManager mDvrWatchedPositionManager;
+    private ConcurrentDvrPlaybackFlags mConcurrentDvrPlaybackFlags;
     private boolean mPaused;
     private final DvrDataManager.ScheduledRecordingListener mScheduledRecordingListener =
             new DvrDataManager.ScheduledRecordingListener() {
@@ -79,10 +76,12 @@
 
     @Override
     public void onAttach(Context context) {
-        AndroidInjection.inject(this);
         super.onAttach(context);
         mDvrDataManger = TvSingletons.getSingletons(context).getDvrDataManager();
         mDvrDataManger.addScheduledRecordingListener(mScheduledRecordingListener);
+        mDvrWatchedPositionManager =
+                TvSingletons.getSingletons(getActivity()).getDvrWatchedPositionManager();
+        mConcurrentDvrPlaybackFlags = HasConcurrentDvrPlaybackFlags.fromContext(context);
     }
 
     @Override
@@ -116,7 +115,9 @@
                         res.getString(R.string.dvr_detail_stop_recording),
                         null,
                         res.getDrawable(R.drawable.lb_ic_stop)));
-        if (mRecordedProgram != null && mRecordedProgram.isPartial()) {
+        if (mConcurrentDvrPlaybackFlags.enabled()
+                && mRecordedProgram != null
+                && mRecordedProgram.isPartial()) {
             if (mDvrWatchedPositionManager.getWatchedStatus(mRecordedProgram)
                     == DvrWatchedPositionManager.DVR_WATCHED_STATUS_WATCHING) {
                 adapter.set(
diff --git a/src/com/android/tv/dvr/ui/browse/DetailsContent.java b/src/com/android/tv/dvr/ui/browse/DetailsContent.java
index b5e0526..e179743 100644
--- a/src/com/android/tv/dvr/ui/browse/DetailsContent.java
+++ b/src/com/android/tv/dvr/ui/browse/DetailsContent.java
@@ -20,11 +20,10 @@
 import android.media.tv.TvContract;
 import android.support.annotation.Nullable;
 import android.text.TextUtils;
-
 import com.android.tv.R;
 import com.android.tv.TvSingletons;
+import com.android.tv.data.Program;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
 import com.android.tv.dvr.data.RecordedProgram;
 import com.android.tv.dvr.data.ScheduledRecording;
 import com.android.tv.dvr.data.SeriesRecording;
@@ -127,10 +126,9 @@
     }
 
     private static String getErrorMessage(Context context, ScheduledRecording recording) {
-        int reason =
-                recording.getFailedReason() == null
-                        ? ScheduledRecording.FAILED_REASON_OTHER
-                        : recording.getFailedReason();
+        int reason = recording.getFailedReason() == null
+                ? ScheduledRecording.FAILED_REASON_OTHER
+                : recording.getFailedReason();
         switch (reason) {
             case ScheduledRecording.FAILED_REASON_PROGRAM_ENDED_BEFORE_RECORDING_STARTED:
                 return context.getString(R.string.dvr_recording_failed_not_started);
@@ -138,7 +136,8 @@
                 return context.getString(R.string.dvr_recording_failed_resource_busy);
             case ScheduledRecording.FAILED_REASON_INPUT_UNAVAILABLE:
                 return context.getString(
-                        R.string.dvr_recording_failed_input_unavailable, recording.getInputId());
+                        R.string.dvr_recording_failed_input_unavailable,
+                        recording.getInputId());
             case ScheduledRecording.FAILED_REASON_INPUT_DVR_UNSUPPORTED:
                 return context.getString(R.string.dvr_recording_failed_input_dvr_unsupported);
             case ScheduledRecording.FAILED_REASON_INSUFFICIENT_SPACE:
diff --git a/src/com/android/tv/dvr/ui/browse/DetailsContentPresenter.java b/src/com/android/tv/dvr/ui/browse/DetailsContentPresenter.java
index fafc70c..6b5fd1f 100644
--- a/src/com/android/tv/dvr/ui/browse/DetailsContentPresenter.java
+++ b/src/com/android/tv/dvr/ui/browse/DetailsContentPresenter.java
@@ -24,7 +24,7 @@
 import android.content.Context;
 import android.graphics.Paint;
 import android.graphics.Paint.FontMetricsInt;
-import androidx.leanback.widget.Presenter;
+import android.support.v17.leanback.widget.Presenter;
 import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -40,10 +40,10 @@
 /**
  * An {@link Presenter} for rendering a detailed description of an DVR item. Typically this
  * Presenter will be used in a {@link
- * androidx.leanback.widget.DetailsOverviewRowPresenter}. Most codes of this class is
- * originated from {@link androidx.leanback.widget.AbstractDetailsDescriptionPresenter}.
+ * 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
- * androidx.leanback.widget.DetailsOverviewRow}.
+ * android.support.v17.leanback.widget.DetailsOverviewRow}.
  */
 public class DetailsContentPresenter extends Presenter {
     /** The ViewHolder for the {@link DetailsContentPresenter}. */
diff --git a/src/com/android/tv/dvr/ui/browse/DetailsViewBackgroundHelper.java b/src/com/android/tv/dvr/ui/browse/DetailsViewBackgroundHelper.java
index 8a4c785..4e41dae 100644
--- a/src/com/android/tv/dvr/ui/browse/DetailsViewBackgroundHelper.java
+++ b/src/com/android/tv/dvr/ui/browse/DetailsViewBackgroundHelper.java
@@ -21,7 +21,7 @@
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
-import androidx.leanback.app.BackgroundManager;
+import android.support.v17.leanback.app.BackgroundManager;
 
 /** The Background Helper. */
 public class DetailsViewBackgroundHelper {
diff --git a/src/com/android/tv/dvr/ui/browse/DvrBrowseActivity.java b/src/com/android/tv/dvr/ui/browse/DvrBrowseActivity.java
index 7262b4a..5743ea5 100644
--- a/src/com/android/tv/dvr/ui/browse/DvrBrowseActivity.java
+++ b/src/com/android/tv/dvr/ui/browse/DvrBrowseActivity.java
@@ -22,13 +22,13 @@
 import android.os.Bundle;
 import com.android.tv.R;
 import com.android.tv.Starter;
-import com.android.tv.perf.StartupMeasureFactory;
+import com.android.tv.perf.PerformanceMonitorManagerFactory;
 
 /** {@link android.app.Activity} for DVR UI. */
 public class DvrBrowseActivity extends Activity {
 
     {
-        StartupMeasureFactory.create().onActivityInit();
+        PerformanceMonitorManagerFactory.create().getStartupMeasure().onActivityInit();
     }
 
     private DvrBrowseFragment mFragment;
diff --git a/src/com/android/tv/dvr/ui/browse/DvrBrowseFragment.java b/src/com/android/tv/dvr/ui/browse/DvrBrowseFragment.java
index 786942e..17ba193 100644
--- a/src/com/android/tv/dvr/ui/browse/DvrBrowseFragment.java
+++ b/src/com/android/tv/dvr/ui/browse/DvrBrowseFragment.java
@@ -21,14 +21,13 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
-import android.text.TextUtils;
-import androidx.leanback.app.BrowseFragment;
-import androidx.leanback.widget.ArrayObjectAdapter;
-import androidx.leanback.widget.ClassPresenterSelector;
-import androidx.leanback.widget.HeaderItem;
-import androidx.leanback.widget.ListRow;
-import androidx.leanback.widget.Presenter;
-import androidx.leanback.widget.TitleViewAdapter;
+import android.support.v17.leanback.app.BrowseFragment;
+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.Presenter;
+import android.support.v17.leanback.widget.TitleViewAdapter;
 import android.util.Log;
 import android.view.View;
 import android.view.ViewTreeObserver.OnGlobalFocusChangeListener;
@@ -476,7 +475,7 @@
         mRecentAdapter.add(recordedProgram);
         String seriesId = recordedProgram.getSeriesId();
         SeriesRecording seriesRecording = null;
-        if (!TextUtils.isEmpty(seriesId)) {
+        if (seriesId != null) {
             seriesRecording = mDvrDataManager.getSeriesRecording(seriesId);
             RecordedProgram latestProgram = mSeriesId2LatestProgram.get(seriesId);
             if (latestProgram == null
@@ -500,7 +499,7 @@
     private void handleRecordedProgramRemoved(RecordedProgram recordedProgram) {
         mRecentAdapter.remove(recordedProgram);
         String seriesId = recordedProgram.getSeriesId();
-        if (!TextUtils.isEmpty(seriesId)) {
+        if (seriesId != null) {
             SeriesRecording seriesRecording = mDvrDataManager.getSeriesRecording(seriesId);
             RecordedProgram latestProgram =
                     mSeriesId2LatestProgram.get(recordedProgram.getSeriesId());
@@ -521,7 +520,7 @@
         mRecentAdapter.change(recordedProgram);
         String seriesId = recordedProgram.getSeriesId();
         SeriesRecording seriesRecording = null;
-        if (!TextUtils.isEmpty(seriesId)) {
+        if (seriesId != null) {
             seriesRecording = mDvrDataManager.getSeriesRecording(seriesId);
             RecordedProgram latestProgram = mSeriesId2LatestProgram.get(seriesId);
             if (latestProgram == null
@@ -664,7 +663,7 @@
             }
         }
         if (getSelectedPosition() >= mRowsAdapter.size()) {
-            setSelectedPosition(mRowsAdapter.size() - 1);
+            setSelectedPosition(mRecentAdapter.size() - 1);
         }
     }
 
diff --git a/src/com/android/tv/dvr/ui/browse/DvrDetailsFragment.java b/src/com/android/tv/dvr/ui/browse/DvrDetailsFragment.java
index a38180a..f90981f 100644
--- a/src/com/android/tv/dvr/ui/browse/DvrDetailsFragment.java
+++ b/src/com/android/tv/dvr/ui/browse/DvrDetailsFragment.java
@@ -25,15 +25,15 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.support.annotation.Nullable;
-import androidx.leanback.app.DetailsFragment;
-import androidx.leanback.widget.ArrayObjectAdapter;
-import androidx.leanback.widget.ClassPresenterSelector;
-import androidx.leanback.widget.DetailsOverviewRow;
-import androidx.leanback.widget.DetailsOverviewRowPresenter;
-import androidx.leanback.widget.OnActionClickedListener;
-import androidx.leanback.widget.PresenterSelector;
-import androidx.leanback.widget.SparseArrayObjectAdapter;
-import androidx.leanback.widget.VerticalGridView;
+import android.support.v17.leanback.app.DetailsFragment;
+import android.support.v17.leanback.widget.ArrayObjectAdapter;
+import android.support.v17.leanback.widget.ClassPresenterSelector;
+import android.support.v17.leanback.widget.DetailsOverviewRow;
+import android.support.v17.leanback.widget.DetailsOverviewRowPresenter;
+import android.support.v17.leanback.widget.OnActionClickedListener;
+import android.support.v17.leanback.widget.PresenterSelector;
+import android.support.v17.leanback.widget.SparseArrayObjectAdapter;
+import android.support.v17.leanback.widget.VerticalGridView;
 import android.text.TextUtils;
 import android.widget.Toast;
 import com.android.tv.R;
diff --git a/src/com/android/tv/dvr/ui/browse/DvrItemPresenter.java b/src/com/android/tv/dvr/ui/browse/DvrItemPresenter.java
index ebdee32..4298d86 100644
--- a/src/com/android/tv/dvr/ui/browse/DvrItemPresenter.java
+++ b/src/com/android/tv/dvr/ui/browse/DvrItemPresenter.java
@@ -19,7 +19,7 @@
 import android.app.Activity;
 import android.content.Context;
 import android.support.annotation.CallSuper;
-import androidx.leanback.widget.Presenter;
+import android.support.v17.leanback.widget.Presenter;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
diff --git a/src/com/android/tv/dvr/ui/browse/DvrListRowPresenter.java b/src/com/android/tv/dvr/ui/browse/DvrListRowPresenter.java
index 625f8f7..a2d1cb2 100644
--- a/src/com/android/tv/dvr/ui/browse/DvrListRowPresenter.java
+++ b/src/com/android/tv/dvr/ui/browse/DvrListRowPresenter.java
@@ -17,7 +17,7 @@
 package com.android.tv.dvr.ui.browse;
 
 import android.content.Context;
-import androidx.leanback.widget.ListRowPresenter;
+import android.support.v17.leanback.widget.ListRowPresenter;
 import android.view.ViewGroup;
 import com.android.tv.R;
 
diff --git a/src/com/android/tv/dvr/ui/browse/RecordedProgramDetailsFragment.java b/src/com/android/tv/dvr/ui/browse/RecordedProgramDetailsFragment.java
index 5f58af8..bf96354 100644
--- a/src/com/android/tv/dvr/ui/browse/RecordedProgramDetailsFragment.java
+++ b/src/com/android/tv/dvr/ui/browse/RecordedProgramDetailsFragment.java
@@ -19,9 +19,9 @@
 import android.content.res.Resources;
 import android.media.tv.TvInputManager;
 import android.os.Bundle;
-import androidx.leanback.widget.Action;
-import androidx.leanback.widget.OnActionClickedListener;
-import androidx.leanback.widget.SparseArrayObjectAdapter;
+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.TvSingletons;
 import com.android.tv.common.util.PermissionUtils;
@@ -32,7 +32,7 @@
 import com.android.tv.dvr.ui.DvrUiHelper;
 import com.android.tv.ui.DetailsActivity;
 
-/** {@link androidx.leanback.app.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 {
     private static final int ACTION_RESUME_PLAYING = 1;
diff --git a/src/com/android/tv/dvr/ui/browse/RecordingCardView.java b/src/com/android/tv/dvr/ui/browse/RecordingCardView.java
index ac7c574..c83ceaf 100644
--- a/src/com/android/tv/dvr/ui/browse/RecordingCardView.java
+++ b/src/com/android/tv/dvr/ui/browse/RecordingCardView.java
@@ -23,16 +23,14 @@
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.support.annotation.Nullable;
-import android.text.Layout;
+import android.support.v17.leanback.widget.BaseCardView;
 import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.View;
-import android.view.ViewTreeObserver;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.ProgressBar;
 import android.widget.TextView;
-import androidx.leanback.widget.BaseCardView;
 import com.android.tv.R;
 import com.android.tv.dvr.data.RecordedProgram;
 import com.android.tv.ui.ViewUtils;
@@ -44,7 +42,7 @@
  */
 public class RecordingCardView extends BaseCardView {
     // This value should be the same with
-    // androidx.leanback.widget.FocusHighlightHelper.BrowseItemFocusHighlight.DURATION_MS
+    // android.support.v17.leanback.widget.FocusHighlightHelper.BrowseItemFocusHighlight.DURATION_MS
     private static final int ANIMATION_DURATION = 150;
     private final ImageView mImageView;
     private final int mImageWidth;
@@ -64,7 +62,6 @@
     private final boolean mExpandTitleWhenFocused;
     private boolean mExpanded;
     private String mDetailBackgroundImageUri;
-    private Layout mTitleViewLayout;
 
     public RecordingCardView(Context context) {
         this(context, false);
@@ -123,14 +120,6 @@
                                                         * value));
                     }
                 });
-        getViewTreeObserver().addOnGlobalLayoutListener(
-                new ViewTreeObserver.OnGlobalLayoutListener() {
-                    @Override
-                    public void onGlobalLayout() {
-                        getViewTreeObserver().removeOnGlobalLayoutListener(this);
-                        mTitleViewLayout = mFoldedTitleView.getLayout();
-                    }
-                });
         mExpandTitleWhenFocused = expandTitleWhenFocused;
     }
 
@@ -165,8 +154,7 @@
      * @param withAnimation {@code true} to expand/fold with animation.
      */
     public void expandTitle(boolean expand, boolean withAnimation) {
-        if (expand != mExpanded && mTitleViewLayout != null
-                && mTitleViewLayout.getEllipsisCount(0) > 0) {
+        if (expand != mExpanded && mFoldedTitleView.getLayout().getEllipsisCount(0) > 0) {
             if (withAnimation) {
                 if (expand) {
                     mExpandTitleAnimator.start();
diff --git a/src/com/android/tv/dvr/ui/browse/RecordingDetailsFragment.java b/src/com/android/tv/dvr/ui/browse/RecordingDetailsFragment.java
index e85f983..243681c 100644
--- a/src/com/android/tv/dvr/ui/browse/RecordingDetailsFragment.java
+++ b/src/com/android/tv/dvr/ui/browse/RecordingDetailsFragment.java
@@ -17,7 +17,7 @@
 package com.android.tv.dvr.ui.browse;
 
 import android.os.Bundle;
-import androidx.leanback.app.DetailsFragment;
+import android.support.v17.leanback.app.DetailsFragment;
 import com.android.tv.TvSingletons;
 import com.android.tv.dvr.data.ScheduledRecording;
 import com.android.tv.ui.DetailsActivity;
diff --git a/src/com/android/tv/dvr/ui/browse/ScheduledRecordingDetailsFragment.java b/src/com/android/tv/dvr/ui/browse/ScheduledRecordingDetailsFragment.java
index 7ef8e59..f08bb12 100644
--- a/src/com/android/tv/dvr/ui/browse/ScheduledRecordingDetailsFragment.java
+++ b/src/com/android/tv/dvr/ui/browse/ScheduledRecordingDetailsFragment.java
@@ -18,9 +18,9 @@
 
 import android.content.res.Resources;
 import android.os.Bundle;
-import androidx.leanback.widget.Action;
-import androidx.leanback.widget.OnActionClickedListener;
-import androidx.leanback.widget.SparseArrayObjectAdapter;
+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.TvSingletons;
diff --git a/src/com/android/tv/dvr/ui/browse/SeriesRecordingDetailsFragment.java b/src/com/android/tv/dvr/ui/browse/SeriesRecordingDetailsFragment.java
index 1c02009..9104ef1 100644
--- a/src/com/android/tv/dvr/ui/browse/SeriesRecordingDetailsFragment.java
+++ b/src/com/android/tv/dvr/ui/browse/SeriesRecordingDetailsFragment.java
@@ -21,21 +21,21 @@
 import android.media.tv.TvInputManager;
 import android.os.Bundle;
 import android.support.annotation.Nullable;
+import android.support.v17.leanback.app.DetailsFragment;
+import android.support.v17.leanback.widget.Action;
+import android.support.v17.leanback.widget.ArrayObjectAdapter;
+import android.support.v17.leanback.widget.ClassPresenterSelector;
+import android.support.v17.leanback.widget.DetailsOverviewRow;
+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.OnActionClickedListener;
+import android.support.v17.leanback.widget.PresenterSelector;
+import android.support.v17.leanback.widget.SparseArrayObjectAdapter;
 import android.text.TextUtils;
-import androidx.leanback.app.DetailsFragment;
-import androidx.leanback.widget.Action;
-import androidx.leanback.widget.ArrayObjectAdapter;
-import androidx.leanback.widget.ClassPresenterSelector;
-import androidx.leanback.widget.DetailsOverviewRow;
-import androidx.leanback.widget.DetailsOverviewRowPresenter;
-import androidx.leanback.widget.HeaderItem;
-import androidx.leanback.widget.ListRow;
-import androidx.leanback.widget.OnActionClickedListener;
-import androidx.leanback.widget.PresenterSelector;
-import androidx.leanback.widget.SparseArrayObjectAdapter;
 import com.android.tv.R;
 import com.android.tv.TvSingletons;
-import com.android.tv.data.api.BaseProgram;
+import com.android.tv.data.BaseProgram;
 import com.android.tv.dvr.DvrDataManager;
 import com.android.tv.dvr.DvrWatchedPositionManager;
 import com.android.tv.dvr.data.RecordedProgram;
diff --git a/src/com/android/tv/dvr/ui/list/BaseDvrSchedulesFragment.java b/src/com/android/tv/dvr/ui/list/BaseDvrSchedulesFragment.java
index 293e1d9..77a6350 100644
--- a/src/com/android/tv/dvr/ui/list/BaseDvrSchedulesFragment.java
+++ b/src/com/android/tv/dvr/ui/list/BaseDvrSchedulesFragment.java
@@ -17,8 +17,8 @@
 package com.android.tv.dvr.ui.list;
 
 import android.os.Bundle;
-import androidx.leanback.app.DetailsFragment;
-import androidx.leanback.widget.ClassPresenterSelector;
+import android.support.v17.leanback.app.DetailsFragment;
+import android.support.v17.leanback.widget.ClassPresenterSelector;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
diff --git a/src/com/android/tv/dvr/ui/list/DvrHistoryFragment.java b/src/com/android/tv/dvr/ui/list/DvrHistoryFragment.java
index 1d93c8c..0ca05fa 100644
--- a/src/com/android/tv/dvr/ui/list/DvrHistoryFragment.java
+++ b/src/com/android/tv/dvr/ui/list/DvrHistoryFragment.java
@@ -17,24 +17,23 @@
 package com.android.tv.dvr.ui.list;
 
 import android.os.Bundle;
+import android.support.v17.leanback.app.DetailsFragment;
+import android.support.v17.leanback.widget.ClassPresenterSelector;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.TextView;
-import androidx.leanback.app.DetailsFragment;
-import androidx.leanback.widget.ClassPresenterSelector;
 import com.android.tv.R;
 import com.android.tv.TvSingletons;
 import com.android.tv.dvr.DvrDataManager;
 import com.android.tv.dvr.data.RecordedProgram;
 import com.android.tv.dvr.data.ScheduledRecording;
 import com.android.tv.dvr.ui.list.SchedulesHeaderRowPresenter.DateHeaderRowPresenter;
-import com.android.tv.common.flags.UiFlags;
 
 /** A fragment to show the DVR history. */
 public class DvrHistoryFragment extends DetailsFragment
         implements DvrDataManager.ScheduledRecordingListener,
-                DvrDataManager.RecordedProgramListener {
+        DvrDataManager.RecordedProgramListener {
 
     private DvrHistoryRowAdapter mRowsAdapter;
     private TextView mEmptyInfoScreenView;
@@ -49,17 +48,11 @@
         presenterSelector.addClassPresenter(
                 ScheduleRow.class, new ScheduleRowPresenter(getContext()));
         TvSingletons singletons = TvSingletons.getSingletons(getContext());
-        UiFlags uiFlags = singletons.getUiFlags();
-        mDvrDataManager = singletons.getDvrDataManager();
-        mRowsAdapter =
-                new DvrHistoryRowAdapter(
-                        getContext(),
-                        presenterSelector,
-                        singletons.getClock(),
-                        mDvrDataManager,
-                        uiFlags);
+        mRowsAdapter = new DvrHistoryRowAdapter(
+                getContext(), presenterSelector, singletons.getClock());
         setAdapter(mRowsAdapter);
         mRowsAdapter.start();
+        mDvrDataManager = singletons.getDvrDataManager();
         mDvrDataManager.addScheduledRecordingListener(this);
         mDvrDataManager.addRecordedProgramListener(this);
         mEmptyInfoScreenView = (TextView) getActivity().findViewById(R.id.empty_info_screen);
@@ -142,6 +135,7 @@
                 hideEmptyMessage();
             }
         }
+
     }
 
     @Override
diff --git a/src/com/android/tv/dvr/ui/list/DvrHistoryRowAdapter.java b/src/com/android/tv/dvr/ui/list/DvrHistoryRowAdapter.java
index a10367f..156d1a7 100644
--- a/src/com/android/tv/dvr/ui/list/DvrHistoryRowAdapter.java
+++ b/src/com/android/tv/dvr/ui/list/DvrHistoryRowAdapter.java
@@ -20,19 +20,20 @@
 import android.content.Context;
 import android.os.Build.VERSION_CODES;
 import android.support.annotation.Nullable;
+import android.support.v17.leanback.widget.ArrayObjectAdapter;
+import android.support.v17.leanback.widget.ClassPresenterSelector;
 import android.text.format.DateUtils;
 import android.util.Log;
-import androidx.leanback.widget.ArrayObjectAdapter;
-import androidx.leanback.widget.ClassPresenterSelector;
 import com.android.tv.R;
+import com.android.tv.TvSingletons;
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.common.util.Clock;
 import com.android.tv.dvr.DvrDataManager;
 import com.android.tv.dvr.data.RecordedProgram;
 import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.recorder.ScheduledProgramReaper;
 import com.android.tv.dvr.ui.list.SchedulesHeaderRow.DateHeaderRow;
 import com.android.tv.util.Utils;
-import com.android.tv.common.flags.UiFlags;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -47,8 +48,8 @@
     private static final boolean DEBUG = false;
 
     private static final long ONE_DAY_MS = TimeUnit.DAYS.toMillis(1);
+    private static final int MAX_HISTORY_DAYS = ScheduledProgramReaper.DAYS;
 
-    private final long mMaxHistoryDays;
     private final Context mContext;
     private final Clock mClock;
     private final DvrDataManager mDvrDataManager;
@@ -56,16 +57,11 @@
     private final Map<Long, ScheduledRecording> mRecordedProgramScheduleMap = new HashMap<>();
 
     public DvrHistoryRowAdapter(
-            Context context,
-            ClassPresenterSelector classPresenterSelector,
-            Clock clock,
-            DvrDataManager dvrDataManager,
-            UiFlags uiFlags) {
+            Context context, ClassPresenterSelector classPresenterSelector, Clock clock) {
         super(classPresenterSelector);
         mContext = context;
         mClock = clock;
-        mDvrDataManager = dvrDataManager;
-        mMaxHistoryDays = uiFlags.maxHistoryDays();
+        mDvrDataManager = TvSingletons.getSingletons(mContext).getDvrDataManager();
         mTitles.add(mContext.getString(R.string.dvr_date_today));
         mTitles.add(mContext.getString(R.string.dvr_date_yesterday));
     }
@@ -82,9 +78,9 @@
         List<RecordedProgram> recordedProgramList = mDvrDataManager.getRecordedPrograms();
 
         recordingList.addAll(
-                recordedProgramsToScheduledRecordings(recordedProgramList, mMaxHistoryDays));
-        recordingList.sort(
-                ScheduledRecording.START_TIME_THEN_PRIORITY_THEN_ID_COMPARATOR.reversed());
+                recordedProgramsToScheduledRecordings(recordedProgramList, MAX_HISTORY_DAYS));
+        recordingList
+                .sort(ScheduledRecording.START_TIME_THEN_PRIORITY_THEN_ID_COMPARATOR.reversed());
         long deadLine = Utils.getFirstMillisecondOfDay(mClock.currentTimeMillis());
         for (int i = 0; i < recordingList.size(); ) {
             ArrayList<ScheduledRecording> section = new ArrayList<>();
@@ -132,7 +128,7 @@
     }
 
     private List<ScheduledRecording> recordedProgramsToScheduledRecordings(
-            List<RecordedProgram> programs, long maxDays) {
+            List<RecordedProgram> programs, int maxDays) {
         List<ScheduledRecording> result = new ArrayList<>();
         for (RecordedProgram recordedProgram : programs) {
             ScheduledRecording scheduledRecording =
@@ -146,12 +142,12 @@
 
     @Nullable
     private ScheduledRecording recordedProgramsToScheduledRecordings(
-            RecordedProgram program, long maxDays) {
+            RecordedProgram program, int maxDays) {
         long firstMillisecondToday = Utils.getFirstMillisecondOfDay(mClock.currentTimeMillis());
-        if (maxDays != 0
-                && maxDays
-                        < Utils.computeDateDifference(
-                                program.getStartTimeUtcMillis(), firstMillisecondToday)) {
+        if (maxDays
+                < Utils.computeDateDifference(
+                        program.getStartTimeUtcMillis(),
+                        firstMillisecondToday)) {
             return null;
         }
         ScheduledRecording scheduledRecording = ScheduledRecording.builder(program).build();
@@ -179,7 +175,7 @@
             return;
         }
         ScheduledRecording schedule =
-                recordedProgramsToScheduledRecordings(program, mMaxHistoryDays);
+                recordedProgramsToScheduledRecordings(program, MAX_HISTORY_DAYS);
         if (schedule == null) {
             return;
         }
@@ -252,10 +248,8 @@
             for (; index < size(); index++) {
                 if (get(index) instanceof ScheduleRow) {
                     ScheduleRow scheduleRow = (ScheduleRow) get(index);
-                    if (ScheduledRecording.START_TIME_THEN_PRIORITY_THEN_ID_COMPARATOR
-                                    .reversed()
-                                    .compare(scheduleRow.getSchedule(), recording)
-                            > 0) {
+                    if (ScheduledRecording.START_TIME_THEN_PRIORITY_THEN_ID_COMPARATOR.reversed()
+                            .compare(scheduleRow.getSchedule(), recording) > 0) {
                         break;
                     }
                     pre = index;
diff --git a/src/com/android/tv/dvr/ui/list/DvrSchedulesActivity.java b/src/com/android/tv/dvr/ui/list/DvrSchedulesActivity.java
index d0884f9..82b8563 100644
--- a/src/com/android/tv/dvr/ui/list/DvrSchedulesActivity.java
+++ b/src/com/android/tv/dvr/ui/list/DvrSchedulesActivity.java
@@ -20,15 +20,13 @@
 import android.app.ProgressDialog;
 import android.os.Bundle;
 import android.support.annotation.IntDef;
-
 import com.android.tv.R;
 import com.android.tv.Starter;
-import com.android.tv.data.api.Program;
+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;
diff --git a/src/com/android/tv/dvr/ui/list/DvrSchedulesFragment.java b/src/com/android/tv/dvr/ui/list/DvrSchedulesFragment.java
index 43a3579..d97b61f 100644
--- a/src/com/android/tv/dvr/ui/list/DvrSchedulesFragment.java
+++ b/src/com/android/tv/dvr/ui/list/DvrSchedulesFragment.java
@@ -17,7 +17,7 @@
 package com.android.tv.dvr.ui.list;
 
 import android.os.Bundle;
-import androidx.leanback.widget.ClassPresenterSelector;
+import android.support.v17.leanback.widget.ClassPresenterSelector;
 import com.android.tv.R;
 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 50bc04c..d376e35 100644
--- a/src/com/android/tv/dvr/ui/list/DvrSeriesSchedulesFragment.java
+++ b/src/com/android/tv/dvr/ui/list/DvrSeriesSchedulesFragment.java
@@ -25,24 +25,20 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
+import android.support.v17.leanback.widget.ClassPresenterSelector;
 import android.transition.Fade;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-
-import androidx.leanback.widget.ClassPresenterSelector;
-
 import com.android.tv.R;
 import com.android.tv.TvSingletons;
 import com.android.tv.data.ChannelDataManager;
-import com.android.tv.data.ProgramImpl;
-import com.android.tv.data.api.Program;
+import com.android.tv.data.Program;
 import com.android.tv.dvr.DvrDataManager;
 import com.android.tv.dvr.DvrDataManager.SeriesRecordingListener;
 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;
 
@@ -57,7 +53,7 @@
             "series_schedules_key_series_recording";
     /**
      * The key for programs which belong to the series recording whose scheduled recording list will
-     * be displayed. Type: List<{@link ProgramImpl}>
+     * be displayed. Type: List<{@link Program}>
      */
     public static final String SERIES_SCHEDULES_KEY_SERIES_PROGRAMS =
             "series_schedules_key_series_programs";
diff --git a/src/com/android/tv/dvr/ui/list/EpisodicProgramRow.java b/src/com/android/tv/dvr/ui/list/EpisodicProgramRow.java
index ccb497f..d580841 100644
--- a/src/com/android/tv/dvr/ui/list/EpisodicProgramRow.java
+++ b/src/com/android/tv/dvr/ui/list/EpisodicProgramRow.java
@@ -17,8 +17,7 @@
 package com.android.tv.dvr.ui.list;
 
 import android.content.Context;
-
-import com.android.tv.data.api.Program;
+import com.android.tv.data.Program;
 import com.android.tv.dvr.data.ScheduledRecording;
 import com.android.tv.dvr.data.ScheduledRecording.Builder;
 import com.android.tv.dvr.ui.DvrUiHelper;
diff --git a/src/com/android/tv/dvr/ui/list/ScheduleRowAdapter.java b/src/com/android/tv/dvr/ui/list/ScheduleRowAdapter.java
index de259f5..ef4a433 100644
--- a/src/com/android/tv/dvr/ui/list/ScheduleRowAdapter.java
+++ b/src/com/android/tv/dvr/ui/list/ScheduleRowAdapter.java
@@ -22,8 +22,8 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
-import androidx.leanback.widget.ArrayObjectAdapter;
-import androidx.leanback.widget.ClassPresenterSelector;
+import android.support.v17.leanback.widget.ArrayObjectAdapter;
+import android.support.v17.leanback.widget.ClassPresenterSelector;
 import android.text.format.DateUtils;
 import android.util.ArraySet;
 import android.util.Log;
diff --git a/src/com/android/tv/dvr/ui/list/ScheduleRowPresenter.java b/src/com/android/tv/dvr/ui/list/ScheduleRowPresenter.java
index ff296f4..11680a0 100644
--- a/src/com/android/tv/dvr/ui/list/ScheduleRowPresenter.java
+++ b/src/com/android/tv/dvr/ui/list/ScheduleRowPresenter.java
@@ -24,7 +24,7 @@
 import android.content.res.Resources;
 import android.os.Build;
 import android.support.annotation.IntDef;
-import androidx.leanback.widget.RowPresenter;
+import android.support.v17.leanback.widget.RowPresenter;
 import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.View;
diff --git a/src/com/android/tv/dvr/ui/list/SchedulesHeaderRow.java b/src/com/android/tv/dvr/ui/list/SchedulesHeaderRow.java
index 5c687cd..bbddc07 100644
--- a/src/com/android/tv/dvr/ui/list/SchedulesHeaderRow.java
+++ b/src/com/android/tv/dvr/ui/list/SchedulesHeaderRow.java
@@ -16,9 +16,8 @@
 
 package com.android.tv.dvr.ui.list;
 
-import com.android.tv.data.api.Program;
+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. */
diff --git a/src/com/android/tv/dvr/ui/list/SchedulesHeaderRowPresenter.java b/src/com/android/tv/dvr/ui/list/SchedulesHeaderRowPresenter.java
index 2550eeb..28a44bf 100644
--- a/src/com/android/tv/dvr/ui/list/SchedulesHeaderRowPresenter.java
+++ b/src/com/android/tv/dvr/ui/list/SchedulesHeaderRowPresenter.java
@@ -19,7 +19,7 @@
 import android.animation.ValueAnimator;
 import android.content.Context;
 import android.graphics.drawable.Drawable;
-import androidx.leanback.widget.RowPresenter;
+import android.support.v17.leanback.widget.RowPresenter;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.OnClickListener;
diff --git a/src/com/android/tv/dvr/ui/list/SeriesScheduleRowAdapter.java b/src/com/android/tv/dvr/ui/list/SeriesScheduleRowAdapter.java
index 2c37754..9a9c94e 100644
--- a/src/com/android/tv/dvr/ui/list/SeriesScheduleRowAdapter.java
+++ b/src/com/android/tv/dvr/ui/list/SeriesScheduleRowAdapter.java
@@ -20,22 +20,19 @@
 import android.content.Context;
 import android.media.tv.TvInputInfo;
 import android.os.Build;
+import android.support.v17.leanback.widget.ClassPresenterSelector;
 import android.util.ArrayMap;
 import android.util.Log;
-
-import androidx.leanback.widget.ClassPresenterSelector;
-
 import com.android.tv.R;
 import com.android.tv.TvSingletons;
 import com.android.tv.common.SoftPreconditions;
-import com.android.tv.data.api.Program;
+import com.android.tv.data.Program;
 import com.android.tv.dvr.DvrDataManager;
 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.ui.list.SchedulesHeaderRow.SeriesRecordingHeaderRow;
 import com.android.tv.util.Utils;
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
diff --git a/src/com/android/tv/dvr/ui/playback/DvrPlaybackActivity.java b/src/com/android/tv/dvr/ui/playback/DvrPlaybackActivity.java
index 4aa1200..f24ad2c 100644
--- a/src/com/android/tv/dvr/ui/playback/DvrPlaybackActivity.java
+++ b/src/com/android/tv/dvr/ui/playback/DvrPlaybackActivity.java
@@ -16,6 +16,7 @@
 
 package com.android.tv.dvr.ui.playback;
 
+import android.app.Activity;
 import android.content.ContentUris;
 import android.content.Intent;
 import android.content.res.Configuration;
@@ -27,12 +28,9 @@
 import com.android.tv.dialog.PinDialogFragment.OnPinCheckedListener;
 import com.android.tv.dvr.data.RecordedProgram;
 import com.android.tv.util.Utils;
-import dagger.android.AndroidInjection;
-import dagger.android.ContributesAndroidInjector;
-import dagger.android.DaggerActivity;
 
 /** Activity to play a {@link RecordedProgram}. */
-public class DvrPlaybackActivity extends DaggerActivity implements OnPinCheckedListener {
+public class DvrPlaybackActivity extends Activity implements OnPinCheckedListener {
     private static final String TAG = "DvrPlaybackActivity";
     private static final boolean DEBUG = false;
 
@@ -41,7 +39,6 @@
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
-        AndroidInjection.inject(this);
         Starter.start(this);
         if (DEBUG) Log.d(TAG, "onCreate");
         super.onCreate(savedInstanceState);
@@ -95,16 +92,4 @@
     void setOnPinCheckListener(OnPinCheckedListener listener) {
         mOnPinCheckedListener = listener;
     }
-
-    /**
-     * Exports {@link DvrPlaybackActivity} for Dagger codegen to create the appropriate injector.
-     */
-    @dagger.Module
-    public abstract static class Module {
-        @ContributesAndroidInjector
-        abstract DvrPlaybackActivity contributesDvrPlaybackActivity();
-
-        @ContributesAndroidInjector
-        abstract DvrPlaybackOverlayFragment contributesDvrPlaybackOverlayFragment();
-    }
 }
diff --git a/src/com/android/tv/dvr/ui/playback/DvrPlaybackControlHelper.java b/src/com/android/tv/dvr/ui/playback/DvrPlaybackControlHelper.java
index 35c5d4e..791d26b 100644
--- a/src/com/android/tv/dvr/ui/playback/DvrPlaybackControlHelper.java
+++ b/src/com/android/tv/dvr/ui/playback/DvrPlaybackControlHelper.java
@@ -26,15 +26,15 @@
 import android.media.tv.TvTrackInfo;
 import android.os.Bundle;
 import android.support.annotation.Nullable;
-import androidx.leanback.media.PlaybackControlGlue;
-import androidx.leanback.widget.AbstractDetailsDescriptionPresenter;
-import androidx.leanback.widget.Action;
-import androidx.leanback.widget.ArrayObjectAdapter;
-import androidx.leanback.widget.PlaybackControlsRow;
-import androidx.leanback.widget.PlaybackControlsRow.ClosedCaptioningAction;
-import androidx.leanback.widget.PlaybackControlsRow.MultiAction;
-import androidx.leanback.widget.PlaybackControlsRowPresenter;
-import androidx.leanback.widget.RowPresenter;
+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.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;
diff --git a/src/com/android/tv/dvr/ui/playback/DvrPlaybackOverlayFragment.java b/src/com/android/tv/dvr/ui/playback/DvrPlaybackOverlayFragment.java
index 0c96cac..1059e85 100644
--- a/src/com/android/tv/dvr/ui/playback/DvrPlaybackOverlayFragment.java
+++ b/src/com/android/tv/dvr/ui/playback/DvrPlaybackOverlayFragment.java
@@ -26,25 +26,24 @@
 import android.media.tv.TvInputManager;
 import android.media.tv.TvTrackInfo;
 import android.os.Bundle;
+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.util.Log;
 import android.view.Display;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.Toast;
-import androidx.leanback.app.PlaybackFragment;
-import androidx.leanback.app.PlaybackFragmentGlueHost;
-import androidx.leanback.widget.ArrayObjectAdapter;
-import androidx.leanback.widget.BaseOnItemViewClickedListener;
-import androidx.leanback.widget.ClassPresenterSelector;
-import androidx.leanback.widget.HeaderItem;
-import androidx.leanback.widget.ListRow;
-import androidx.leanback.widget.Presenter;
-import androidx.leanback.widget.RowPresenter;
-import androidx.leanback.widget.SinglePresenterSelector;
 import com.android.tv.R;
-import com.android.tv.audio.AudioManagerHelper;
-import com.android.tv.common.buildtype.HasBuildType.BuildType;
-import com.android.tv.data.api.BaseProgram;
+import com.android.tv.TvSingletons;
+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;
@@ -56,11 +55,8 @@
 import com.android.tv.util.TvSettings;
 import com.android.tv.util.TvTrackInfoUtils;
 import com.android.tv.util.Utils;
-import dagger.android.AndroidInjection;
-import com.android.tv.common.flags.LegacyFlags;
 import java.util.ArrayList;
 import java.util.List;
-import javax.inject.Inject;
 
 public class DvrPlaybackOverlayFragment extends PlaybackFragment {
     // TODO: Handles audio focus. Deals with block and ratings.
@@ -79,7 +75,7 @@
     private ArrayObjectAdapter mRowsAdapter;
     private SortedArrayAdapter<BaseProgram> mRelatedRecordingsRowAdapter;
     private DvrPlaybackCardPresenter mRelatedRecordingCardPresenter;
-    private AudioManagerHelper mAudioManagerHelper;
+    private DvrDataManager mDvrDataManager;
     private AppLayerTvView mTvView;
     private View mBlockScreenView;
     private ListRow mRelatedRecordingsRow;
@@ -101,24 +97,9 @@
                 }
             };
 
-    @Inject DvrDataManager mDvrDataManager;
-    @Inject LegacyFlags mLegacyFlags;
-    @Inject BuildType buildType;
-
-    @Override
-    public void onAttach(Context context) {
-        if (DEBUG) {
-            Log.d(TAG, "onAttach");
-        }
-        AndroidInjection.inject(this);
-        super.onAttach(context);
-    }
-
     @Override
     public void onCreate(Bundle savedInstanceState) {
-        if (DEBUG) {
-            Log.d(TAG, "onCreate");
-        }
+        if (DEBUG) Log.d(TAG, "onCreate");
         super.onCreate(savedInstanceState);
         mVerticalPaddingBase =
                 getActivity()
@@ -134,6 +115,7 @@
                         .getResources()
                         .getDimensionPixelOffset(
                                 R.dimen.dvr_playback_overlay_padding_top_no_secondary_row);
+        mDvrDataManager = TvSingletons.getSingletons(getActivity()).getDvrDataManager();
         if (!mDvrDataManager.isRecordedProgramLoadFinished()) {
             mDvrDataManager.addRecordedProgramLoadFinishedListener(
                     new DvrDataManager.OnRecordedProgramLoadFinishedListener() {
@@ -171,8 +153,6 @@
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
         mTvView = getActivity().findViewById(R.id.dvr_tv_view);
-        mTvView.setUseSecureSurface(
-                buildType != BuildType.ENG && !mLegacyFlags.enableDeveloperFeatures());
         mBlockScreenView = getActivity().findViewById(R.id.block_screen);
         mDvrPlayer = new DvrPlayer(mTvView, getActivity());
         mMediaSessionHelper =
@@ -260,16 +240,13 @@
                             setFadingEnabled(false);
                             long programId =
                                     ((RecordedProgram) itemViewHolder.view.getTag()).getId();
-                            if (DEBUG) {
-                                Log.d(TAG, "Play Related Recording:" + programId);
-                            }
+                            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);
                         }
                     }
                 });
-        mAudioManagerHelper = new AudioManagerHelper(getActivity(), mDvrPlayer.getView());
         if (mProgram != null) {
             setUpRows();
             preparePlayback(getActivity().getIntent());
@@ -278,9 +255,7 @@
 
     @Override
     public void onPause() {
-        if (DEBUG) {
-            Log.d(TAG, "onPause");
-        }
+        if (DEBUG) Log.d(TAG, "onPause");
         super.onPause();
         if (mMediaSessionHelper.getPlaybackState() == PlaybackState.STATE_FAST_FORWARDING
                 || mMediaSessionHelper.getPlaybackState() == PlaybackState.STATE_REWINDING) {
@@ -295,12 +270,9 @@
 
     @Override
     public void onDestroy() {
-        if (DEBUG) {
-            Log.d(TAG, "onDestroy");
-        }
+        if (DEBUG) Log.d(TAG, "onDestroy");
         mPlaybackControlHelper.unregisterCallback();
         mMediaSessionHelper.release();
-        mAudioManagerHelper.abandonAudioFocus();
         mRelatedRecordingCardPresenter.unbindAllViewHolders();
         mDvrPlayer.release();
         super.onDestroy();
@@ -444,7 +416,6 @@
     private void preparePlayback(Intent intent) {
         mMediaSessionHelper.setupPlayback(mProgram, getSeekTimeFromIntent(intent));
         mPlaybackControlHelper.updateSecondaryRow(false, false);
-        mAudioManagerHelper.requestAudioFocus();
         getActivity().getMediaController().getTransportControls().prepare();
         updateRelatedRecordingsRow();
     }
diff --git a/src/com/android/tv/dvr/ui/playback/DvrPlaybackSideFragment.java b/src/com/android/tv/dvr/ui/playback/DvrPlaybackSideFragment.java
index 95858e3..b4481df 100644
--- a/src/com/android/tv/dvr/ui/playback/DvrPlaybackSideFragment.java
+++ b/src/com/android/tv/dvr/ui/playback/DvrPlaybackSideFragment.java
@@ -19,8 +19,8 @@
 import android.media.tv.TvTrackInfo;
 import android.os.Bundle;
 import android.support.annotation.NonNull;
-import androidx.leanback.app.GuidedStepFragment;
-import androidx.leanback.widget.GuidedAction;
+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;
diff --git a/src/com/android/tv/dvr/ui/playback/DvrPlayer.java b/src/com/android/tv/dvr/ui/playback/DvrPlayer.java
index 6cfa2e2..d14646b 100644
--- a/src/com/android/tv/dvr/ui/playback/DvrPlayer.java
+++ b/src/com/android/tv/dvr/ui/playback/DvrPlayer.java
@@ -326,11 +326,6 @@
         return mProgram;
     }
 
-    /** Returns the DVR tv view. */
-    public DvrTvView getView() {
-        return mTvView;
-    }
-
     /** Returns the currrent playback posistion in msecs. */
     public long getPlaybackPosition() {
         return mTimeShiftCurrentPositionMs;
@@ -521,17 +516,13 @@
                                 for (TvTrackInfo trackInfo : trackInfos) {
                                     if (trackInfo.getId().equals(trackId)) {
                                         float videoAspectRatio;
-                                        float videoPixelAspectRatio =
-                                                trackInfo.getVideoPixelAspectRatio();
                                         int videoWidth = trackInfo.getVideoWidth();
                                         int videoHeight = trackInfo.getVideoHeight();
                                         if (videoWidth > 0 && videoHeight > 0) {
                                             videoAspectRatio =
-                                                    (float) trackInfo.getVideoWidth()
+                                                    trackInfo.getVideoPixelAspectRatio()
+                                                            * trackInfo.getVideoWidth()
                                                             / trackInfo.getVideoHeight();
-                                            videoAspectRatio *=
-                                                    videoPixelAspectRatio > 0 ?
-                                                            videoPixelAspectRatio : 1;
                                         } else {
                                             // Aspect ratio is unknown. Pass the message to
                                             // listeners.
diff --git a/src/com/android/tv/features/TvFeatures.java b/src/com/android/tv/features/TvFeatures.java
index a18d9c8..208d53f 100644
--- a/src/com/android/tv/features/TvFeatures.java
+++ b/src/com/android/tv/features/TvFeatures.java
@@ -27,11 +27,14 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.os.Build;
-
+import android.support.annotation.VisibleForTesting;
+import com.android.tv.common.experiments.Experiments;
 import com.android.tv.common.feature.CommonFeatures;
+import com.android.tv.common.feature.ExperimentFeature;
 import com.android.tv.common.feature.Feature;
 import com.android.tv.common.feature.FeatureUtils;
 import com.android.tv.common.feature.FlagFeature;
+import com.android.tv.common.feature.PropertyFeature;
 import com.android.tv.common.feature.Sdk;
 import com.android.tv.common.feature.TestableFeature;
 import com.android.tv.common.flags.has.HasUiFlags;
@@ -39,7 +42,7 @@
 import com.android.tv.common.util.PermissionUtils;
 
 /**
- * List of {@link Feature} for the TV app.
+ * List of {@link Feature} for the Live TV App.
  *
  * <p>Remove the {@code Feature} once it is launched.
  */
@@ -48,6 +51,16 @@
     /** When enabled store network affiliation information to TV provider */
     public static final Feature STORE_NETWORK_AFFILIATION = ENG_ONLY_FEATURE;
 
+    /** When enabled use system setting for turning on analytics. */
+    public static final Feature ANALYTICS_OPT_IN =
+            ExperimentFeature.from(Experiments.ENABLE_ANALYTICS_VIA_CHECKBOX);
+    /**
+     * Analytics that include sensitive information such as channel or program identifiers.
+     *
+     * <p>See <a href="http://b/22062676">b/22062676</a>
+     */
+    public static final Feature ANALYTICS_V2 = and(ON, ANALYTICS_OPT_IN);
+
     private static final Feature TV_PROVIDER_ALLOWS_INSERT_TO_PROGRAM_TABLE =
             or(Sdk.AT_LEAST_O, PartnerFeatures.TVPROVIDER_ALLOWS_SYSTEM_INSERTS_TO_PROGRAM_TABLE);
 
@@ -74,7 +87,7 @@
             or(
                     FlagFeature.from(
                             context -> HasSingletons.get(HasUiFlags.class, context),
-                            input -> input.getUiFlags().unhideLauncher()),
+                            input -> input.getUiFlags().uhideLauncher()),
                     // If LC app runs as non-system app, we unhide the app.
                     not(PermissionUtils::hasAccessAllEpg));
 
@@ -101,5 +114,8 @@
     /** Use input blacklist to disable partner's tuner input. */
     public static final Feature USE_PARTNER_INPUT_BLACKLIST = ON;
 
+    @VisibleForTesting
+    public static final Feature TEST_FEATURE = PropertyFeature.create("test_feature", false);
+
     private TvFeatures() {}
 }
diff --git a/src/com/android/tv/guide/GenreListAdapter.java b/src/com/android/tv/guide/GenreListAdapter.java
index 995b053..b4baf42 100644
--- a/src/com/android/tv/guide/GenreListAdapter.java
+++ b/src/com/android/tv/guide/GenreListAdapter.java
@@ -18,7 +18,7 @@
 
 import android.content.Context;
 import android.support.annotation.MainThread;
-import androidx.recyclerview.widget.RecyclerView;
+import android.support.v7.widget.RecyclerView;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
diff --git a/src/com/android/tv/guide/ProgramGrid.java b/src/com/android/tv/guide/ProgramGrid.java
index 96e161c..caafb04 100644
--- a/src/com/android/tv/guide/ProgramGrid.java
+++ b/src/com/android/tv/guide/ProgramGrid.java
@@ -19,7 +19,7 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Rect;
-import androidx.leanback.widget.VerticalGridView;
+import android.support.v17.leanback.widget.VerticalGridView;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.Range;
@@ -256,19 +256,8 @@
                 scrollToPosition(getAdapter().getItemCount() - 1);
                 return null;
             } else if (getSelectedPosition() == getAdapter().getItemCount() - 1) {
-                int itemCount = getLayoutManager().getItemCount();
-                int childCount = getChildCount();
-                // b/129466363 For an item which overalps with previous layout GridLayoutManager
-                // will scroll to first child of current layout, instead of going to previous one.
-                // smoothscrollToPosition will invalidate all layouts and scroll to position 0.
-                // This condition checks for an item which overlaps with the first layout
-                if (itemCount > 2 * (childCount + 1) || itemCount <= childCount) {
-                    scrollToPosition(0);
-                    return null;
-                } else {
-                    smoothScrollToPosition(0);
-                    return getChildAt(0);
-                }
+                scrollToPosition(0);
+                return null;
             }
             return focused;
         }
diff --git a/src/com/android/tv/guide/ProgramGuide.java b/src/com/android/tv/guide/ProgramGuide.java
index 8ae61e8..bc1b11b 100644
--- a/src/com/android/tv/guide/ProgramGuide.java
+++ b/src/com/android/tv/guide/ProgramGuide.java
@@ -32,7 +32,10 @@
 import android.preference.PreferenceManager;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
-import androidx.recyclerview.widget.RecyclerView;
+import android.support.v17.leanback.widget.OnChildSelectedListener;
+import android.support.v17.leanback.widget.SearchOrbView;
+import android.support.v17.leanback.widget.VerticalGridView;
+import android.support.v7.widget.RecyclerView;
 import android.util.Log;
 import android.view.View;
 import android.view.View.MeasureSpec;
@@ -41,11 +44,6 @@
 import android.view.ViewTreeObserver;
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener;
-
-import androidx.leanback.widget.OnChildSelectedListener;
-import androidx.leanback.widget.SearchOrbView;
-import androidx.leanback.widget.VerticalGridView;
-
 import com.android.tv.ChannelTuner;
 import com.android.tv.MainActivity;
 import com.android.tv.R;
@@ -67,9 +65,7 @@
 import com.android.tv.ui.hideable.AutoHideScheduler;
 import com.android.tv.util.TvInputManagerHelper;
 import com.android.tv.util.Utils;
-
-import com.android.tv.common.flags.UiFlags;
-
+import com.android.tv.common.flags.BackendKnobsFlags;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
@@ -116,7 +112,6 @@
     private final int mAnimationDuration;
     private final int mDetailPadding;
     private final SearchOrbView mSearchOrb;
-    private final UiFlags mUiFlags;
     private int mCurrentTimeIndicatorWidth;
 
     private final View mContainer;
@@ -190,14 +185,15 @@
         mActivity = activity;
         TvSingletons singletons = TvSingletons.getSingletons(mActivity);
         mPerformanceMonitor = singletons.getPerformanceMonitor();
-        mUiFlags = singletons.getUiFlags();
+        BackendKnobsFlags backendKnobsFlags = singletons.getBackendKnobs();
         mProgramManager =
                 new ProgramManager(
                         tvInputManagerHelper,
                         channelDataManager,
                         programDataManager,
                         dvrDataManager,
-                        dvrScheduleManager);
+                        dvrScheduleManager,
+                        backendKnobsFlags);
         mChannelTuner = channelTuner;
         mTracker = tracker;
         mPreShowRunnable = preShowRunnable;
@@ -265,7 +261,7 @@
                         }
                     });
             mSidePanelGridView.setOnChildSelectedListener(
-                    new androidx.leanback.widget.OnChildSelectedListener() {
+                    new android.support.v17.leanback.widget.OnChildSelectedListener() {
                         @Override
                         public void onChildSelected(ViewGroup viewGroup, View view, int i, long l) {
                             mSearchOrb.animate().alpha(i == 0 ? 1.0f : 0.0f);
@@ -286,8 +282,7 @@
                         res.getInteger(R.integer.max_recycled_view_pool_epg_header_row_item));
         mTimelineRow.setAdapter(mTimeListAdapter);
 
-        ProgramTableAdapter programTableAdapter =
-                new ProgramTableAdapter(mActivity, this, mUiFlags);
+        ProgramTableAdapter programTableAdapter = new ProgramTableAdapter(mActivity, this);
         programTableAdapter.registerAdapterDataObserver(
                 new RecyclerView.AdapterDataObserver() {
                     @Override
diff --git a/src/com/android/tv/guide/ProgramItemView.java b/src/com/android/tv/guide/ProgramItemView.java
index 5ec293f..a46beab 100644
--- a/src/com/android/tv/guide/ProgramItemView.java
+++ b/src/com/android/tv/guide/ProgramItemView.java
@@ -23,7 +23,6 @@
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.LayerDrawable;
 import android.graphics.drawable.StateListDrawable;
-import android.os.Build;
 import android.os.Handler;
 import android.text.SpannableStringBuilder;
 import android.text.Spanned;
@@ -35,7 +34,6 @@
 import android.view.ViewGroup;
 import android.widget.TextView;
 import android.widget.Toast;
-
 import com.android.tv.MainActivity;
 import com.android.tv.R;
 import com.android.tv.TvSingletons;
@@ -43,22 +41,17 @@
 import com.android.tv.common.feature.CommonFeatures;
 import com.android.tv.common.util.Clock;
 import com.android.tv.data.ChannelDataManager;
+import com.android.tv.data.Program;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
 import com.android.tv.dvr.DvrManager;
 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;
-
-import dagger.android.HasAndroidInjector;
-
 import java.lang.reflect.InvocationTargetException;
 import java.util.concurrent.TimeUnit;
 
-import javax.inject.Inject;
-
 public class ProgramItemView extends TextView {
     private static final String TAG = "ProgramItemView";
 
@@ -80,8 +73,8 @@
     private static TextAppearanceSpan sGrayedOutEpisodeTitleStyle;
 
     private final DvrManager mDvrManager;
-    @Inject Clock mClock;
-    @Inject ChannelDataManager mChannelDataManager;
+    private final Clock mClock;
+    private final ChannelDataManager mChannelDataManager;
     private ProgramGuide mProgramGuide;
     private TableEntry mTableEntry;
     private int mMaxWidthForRipple;
@@ -209,11 +202,12 @@
 
     public ProgramItemView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
-        ((HasAndroidInjector) context).androidInjector().inject(this);
         setOnClickListener(ON_CLICKED);
         setOnFocusChangeListener(ON_FOCUS_CHANGED);
         TvSingletons singletons = TvSingletons.getSingletons(getContext());
         mDvrManager = singletons.getDvrManager();
+        mChannelDataManager = singletons.getChannelDataManager();
+        mClock = singletons.getClock();
     }
 
     private void initIfNeeded() {
@@ -536,9 +530,6 @@
     }
 
     private static int getStateCount(StateListDrawable stateListDrawable) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
-            return stateListDrawable.getStateCount();
-        }
         try {
             Object stateCount =
                     StateListDrawable.class
@@ -555,9 +546,6 @@
     }
 
     private static Drawable getStateDrawable(StateListDrawable stateListDrawable, int index) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
-            return stateListDrawable.getStateDrawable(index);
-        }
         try {
             Object drawable =
                     StateListDrawable.class
diff --git a/src/com/android/tv/guide/ProgramListAdapter.java b/src/com/android/tv/guide/ProgramListAdapter.java
index 68ae43e..397bacf 100644
--- a/src/com/android/tv/guide/ProgramListAdapter.java
+++ b/src/com/android/tv/guide/ProgramListAdapter.java
@@ -17,7 +17,7 @@
 package com.android.tv.guide;
 
 import android.content.res.Resources;
-import androidx.recyclerview.widget.RecyclerView;
+import android.support.v7.widget.RecyclerView;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
diff --git a/src/com/android/tv/guide/ProgramManager.java b/src/com/android/tv/guide/ProgramManager.java
index 516a4d9..3a5a4a0 100644
--- a/src/com/android/tv/guide/ProgramManager.java
+++ b/src/com/android/tv/guide/ProgramManager.java
@@ -21,20 +21,18 @@
 import android.support.annotation.VisibleForTesting;
 import android.util.ArraySet;
 import android.util.Log;
-
 import com.android.tv.data.ChannelDataManager;
 import com.android.tv.data.GenreItems;
+import com.android.tv.data.Program;
 import com.android.tv.data.ProgramDataManager;
-import com.android.tv.data.ProgramImpl;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
 import com.android.tv.dvr.DvrDataManager;
 import com.android.tv.dvr.DvrScheduleManager;
 import com.android.tv.dvr.DvrScheduleManager.OnConflictStateChangeListener;
 import com.android.tv.dvr.data.ScheduledRecording;
 import com.android.tv.util.TvInputManagerHelper;
 import com.android.tv.util.Utils;
-
+import com.android.tv.common.flags.BackendKnobsFlags;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -62,6 +60,7 @@
     private final ProgramDataManager mProgramDataManager;
     private final DvrDataManager mDvrDataManager; // Only set if DVR is enabled
     private final DvrScheduleManager mDvrScheduleManager;
+    private final BackendKnobsFlags mBackendKnobsFlags;
 
     private long mStartUtcMillis;
     private long mEndUtcMillis;
@@ -125,8 +124,16 @@
                 }
 
                 @Override
-                public void onChannelUpdated() {
-                    updateTableEntriesWithoutNotification(false);
+                public void onSingleChannelUpdated(long channelId) {
+                    boolean parentalControlsEnabled =
+                            mTvInputManagerHelper
+                                    .getParentalControlSettings()
+                                    .isParentalControlsEnabled();
+                    // Inline the updating of the mChannelIdEntriesMap here so we can only call
+                    // getParentalControlSettings once.
+                    List<TableEntry> entries =
+                            createProgramEntries(channelId, parentalControlsEnabled);
+                    mChannelIdEntriesMap.put(channelId, entries);
                     notifyTableEntriesUpdated();
                 }
             };
@@ -208,12 +215,14 @@
             ChannelDataManager channelDataManager,
             ProgramDataManager programDataManager,
             @Nullable DvrDataManager dvrDataManager,
-            @Nullable DvrScheduleManager dvrScheduleManager) {
+            @Nullable DvrScheduleManager dvrScheduleManager,
+            BackendKnobsFlags backendKnobsFlags) {
         mTvInputManagerHelper = tvInputManagerHelper;
         mChannelDataManager = channelDataManager;
         mProgramDataManager = programDataManager;
         mDvrDataManager = dvrDataManager;
         mDvrScheduleManager = dvrScheduleManager;
+        mBackendKnobsFlags = backendKnobsFlags;
     }
 
     void programGuideVisibilityChanged(boolean visible) {
@@ -242,6 +251,7 @@
                 mDvrScheduleManager.removeOnConflictStateChangeListener(
                         mOnConflictStateChangeListener);
             }
+            mChannelIdEntriesMap.clear();
         }
     }
 
@@ -416,12 +426,14 @@
     }
 
     /**
-     * Returns an entry as {@link ProgramImpl} for a given {@code channelId} and {@code index} of
-     * entries within the currently managed time range. Returned {@link ProgramImpl} can be a dummy
-     * one (e.g., whose channelId is INVALID_ID), when it corresponds to a gap between programs.
+     * 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) {
-        mProgramDataManager.prefetchChannel(channelId, index);
+        if (mBackendKnobsFlags.enablePartialProgramFetch()) {
+            mProgramDataManager.prefetchChannel(channelId);
+        }
         return mChannelIdEntriesMap.get(channelId).get(index);
     }
 
@@ -695,7 +707,7 @@
     /**
      * 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
-     * androidx.leanback.widget.HorizontalGridView} ignores margins between items.
+     * android.support.v17.leanback.widget.HorizontalGridView} ignores margins between items.
      */
     static class TableEntry {
         /** Channel ID which this entry is included. */
@@ -725,7 +737,7 @@
 
         private TableEntry(
                 long channelId,
-                ProgramImpl program,
+                Program program,
                 long entryStartUtcMillis,
                 long entryEndUtcMillis,
                 boolean isBlocked) {
@@ -747,7 +759,7 @@
             mIsBlocked = isBlocked;
         }
 
-        /** A stable id useful for {@link androidx.recyclerview.widget.RecyclerView.Adapter}. */
+        /** 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;
diff --git a/src/com/android/tv/guide/ProgramRow.java b/src/com/android/tv/guide/ProgramRow.java
index 6f8f31c..3317c15 100644
--- a/src/com/android/tv/guide/ProgramRow.java
+++ b/src/com/android/tv/guide/ProgramRow.java
@@ -18,7 +18,7 @@
 
 import android.content.Context;
 import android.graphics.Rect;
-import androidx.recyclerview.widget.LinearLayoutManager;
+import android.support.v7.widget.LinearLayoutManager;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.Range;
diff --git a/src/com/android/tv/guide/ProgramRowAccessibilityDelegate.java b/src/com/android/tv/guide/ProgramRowAccessibilityDelegate.java
index a6a4624..5e498be 100644
--- a/src/com/android/tv/guide/ProgramRowAccessibilityDelegate.java
+++ b/src/com/android/tv/guide/ProgramRowAccessibilityDelegate.java
@@ -17,8 +17,8 @@
 package com.android.tv.guide;
 
 import android.os.Bundle;
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.recyclerview.widget.RecyclerViewAccessibilityDelegate;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.RecyclerViewAccessibilityDelegate;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
diff --git a/src/com/android/tv/guide/ProgramTableAdapter.java b/src/com/android/tv/guide/ProgramTableAdapter.java
index aed8b90..7576bf5 100644
--- a/src/com/android/tv/guide/ProgramTableAdapter.java
+++ b/src/com/android/tv/guide/ProgramTableAdapter.java
@@ -28,8 +28,8 @@
 import android.os.Handler;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.recyclerview.widget.RecyclerView.RecycledViewPool;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.RecyclerView.RecycledViewPool;
 import android.text.Html;
 import android.text.Spannable;
 import android.text.SpannableString;
@@ -47,14 +47,13 @@
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
-
 import com.android.tv.R;
 import com.android.tv.TvSingletons;
 import com.android.tv.common.feature.CommonFeatures;
 import com.android.tv.common.util.CommonUtils;
+import com.android.tv.data.Program;
+import com.android.tv.data.Program.CriticScore;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
-import com.android.tv.data.api.Program.CriticScore;
 import com.android.tv.dvr.DvrDataManager;
 import com.android.tv.dvr.DvrManager;
 import com.android.tv.dvr.data.ScheduledRecording;
@@ -68,8 +67,6 @@
 import com.android.tv.util.images.ImageLoader.ImageLoaderCallback;
 import com.android.tv.util.images.ImageLoader.LoadTvInputLogoTask;
 
-import com.android.tv.common.flags.UiFlags;
-
 import java.util.ArrayList;
 import java.util.List;
 
@@ -112,11 +109,10 @@
     private final String mRecordingInProgressText;
     private final int mDvrPaddingStartWithTrack;
     private final int mDvrPaddingStartWithOutTrack;
-    private final UiFlags mUiFlags;
 
     private RecyclerView mRecyclerView;
 
-    ProgramTableAdapter(Context context, ProgramGuide programGuide, UiFlags uiFlags) {
+    ProgramTableAdapter(Context context, ProgramGuide programGuide) {
         mContext = context;
         mAccessibilityManager =
                 (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
@@ -130,7 +126,6 @@
         }
         mProgramGuide = programGuide;
         mProgramManager = programGuide.getProgramManager();
-        mUiFlags = uiFlags;
 
         Resources res = context.getResources();
         mChannelLogoWidth =
@@ -661,35 +656,6 @@
                     mDvrIndicator.setVisibility(View.GONE);
                 }
 
-                if (mUiFlags.enableCriticRatings()) {
-                    // display critic scores if any exist
-                    List<CriticScore> criticScores = program.getCriticScores();
-                    if (criticScores != null) {
-                        // inflate more critic score views if required
-                        if (criticScores.size() > mCriticScoreViews.size()) {
-                            LayoutInflater inflater = LayoutInflater.from(mContext);
-                            LinearLayout layout =
-                                    (LinearLayout)
-                                            inflater.inflate(
-                                                    R.layout.program_guide_critic_score_layout,
-                                                    null);
-                            mCriticScoreViews.add(layout);
-                        }
-                        // fill critic score views and add to layout
-                        for (int i = 0; i < criticScores.size(); i++) {
-                            View criticScoreView = mCriticScoreViews.get(i);
-                            ViewParent previousParentView = criticScoreView.getParent();
-                            if (previousParentView != null
-                                    && previousParentView instanceof ViewGroup) {
-                                ((ViewGroup) previousParentView).removeView(criticScoreView);
-                            }
-                            updateCriticScoreView(
-                                    this, program.getId(), criticScores.get(i), criticScoreView);
-                            mCriticScoresLayout.addView(mCriticScoreViews.get(i));
-                        }
-                    }
-                }
-
                 if (blockedRating == null) {
                     mBlockView.setVisibility(View.GONE);
                     updateTextView(mDescriptionView, program.getDescription());
diff --git a/src/com/android/tv/guide/TimeListAdapter.java b/src/com/android/tv/guide/TimeListAdapter.java
index 62fec69..9c10c95 100644
--- a/src/com/android/tv/guide/TimeListAdapter.java
+++ b/src/com/android/tv/guide/TimeListAdapter.java
@@ -17,7 +17,7 @@
 package com.android.tv.guide;
 
 import android.content.res.Resources;
-import androidx.recyclerview.widget.RecyclerView;
+import android.support.v7.widget.RecyclerView;
 import android.text.format.DateFormat;
 import android.view.LayoutInflater;
 import android.view.View;
diff --git a/src/com/android/tv/guide/TimelineGridView.java b/src/com/android/tv/guide/TimelineGridView.java
index 2d25787..c4922b7 100644
--- a/src/com/android/tv/guide/TimelineGridView.java
+++ b/src/com/android/tv/guide/TimelineGridView.java
@@ -17,8 +17,8 @@
 package com.android.tv.guide;
 
 import android.content.Context;
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
 import android.util.AttributeSet;
 import android.view.View;
 
diff --git a/src/com/android/tv/menu/ActionCardView.java b/src/com/android/tv/menu/ActionCardView.java
index 0e789c6..3ecd5f5 100644
--- a/src/com/android/tv/menu/ActionCardView.java
+++ b/src/com/android/tv/menu/ActionCardView.java
@@ -19,7 +19,6 @@
 import android.content.Context;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.ImageView;
 import android.widget.RelativeLayout;
 import android.widget.TextView;
@@ -94,13 +93,6 @@
         }
     }
 
-    /** Request focus and accessibility focus on card view. */
-    @Override
-    public boolean requestFocusWithAccessibility() {
-        return requestFocus() &&
-                performAccessibilityAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
-    }
-
     @Override
     public void onRecycled() {}
 }
diff --git a/src/com/android/tv/menu/AppLinkCardView.java b/src/com/android/tv/menu/AppLinkCardView.java
index 49d32fe..fd93c31 100644
--- a/src/com/android/tv/menu/AppLinkCardView.java
+++ b/src/com/android/tv/menu/AppLinkCardView.java
@@ -26,13 +26,13 @@
 import android.graphics.drawable.Drawable;
 import android.os.AsyncTask;
 import android.support.annotation.Nullable;
+import android.support.v7.graphics.Palette;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.TextView;
-import androidx.palette.graphics.Palette;
 import com.android.tv.MainActivity;
 import com.android.tv.R;
 import com.android.tv.data.api.Channel;
diff --git a/src/com/android/tv/menu/BaseCardView.java b/src/com/android/tv/menu/BaseCardView.java
index ed78cb7..3a94ebb 100644
--- a/src/com/android/tv/menu/BaseCardView.java
+++ b/src/com/android/tv/menu/BaseCardView.java
@@ -27,7 +27,6 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewOutlineProvider;
-import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 import com.android.tv.R;
@@ -136,13 +135,6 @@
         }
     }
 
-    /** Request focus and accessibility focus on card view. */
-    @Override
-    public boolean requestFocusWithAccessibility() {
-        return requestFocus() &&
-                performAccessibilityAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
-    }
-
     /** Sets text of this card view. */
     public void setText(int resId) {
         if (mTextResId != resId) {
diff --git a/src/com/android/tv/menu/ChannelCardView.java b/src/com/android/tv/menu/ChannelCardView.java
index 7fe5e49..76056ee 100644
--- a/src/com/android/tv/menu/ChannelCardView.java
+++ b/src/com/android/tv/menu/ChannelCardView.java
@@ -26,14 +26,12 @@
 import android.widget.ImageView;
 import android.widget.ProgressBar;
 import android.widget.TextView;
-
 import com.android.tv.MainActivity;
 import com.android.tv.R;
+import com.android.tv.data.Program;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
 import com.android.tv.parental.ParentalControlSettings;
 import com.android.tv.util.images.ImageLoader;
-
 import java.util.Objects;
 
 /** A view to render channel card. */
diff --git a/src/com/android/tv/menu/ChannelsPosterPrefetcher.java b/src/com/android/tv/menu/ChannelsPosterPrefetcher.java
index 3a50230..9cecb9c 100644
--- a/src/com/android/tv/menu/ChannelsPosterPrefetcher.java
+++ b/src/com/android/tv/menu/ChannelsPosterPrefetcher.java
@@ -23,15 +23,13 @@
 import android.support.annotation.MainThread;
 import android.support.annotation.NonNull;
 import android.util.Log;
-
 import com.android.tv.R;
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.common.WeakHandler;
 import com.android.tv.data.ChannelImpl;
+import com.android.tv.data.Program;
 import com.android.tv.data.ProgramDataManager;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
-
 import java.util.List;
 
 /** A poster image prefetcher to show the program poster art in the Channels row faster. */
diff --git a/src/com/android/tv/menu/ChannelsRow.java b/src/com/android/tv/menu/ChannelsRow.java
index dbfc782..7d03bf2 100644
--- a/src/com/android/tv/menu/ChannelsRow.java
+++ b/src/com/android/tv/menu/ChannelsRow.java
@@ -73,7 +73,6 @@
             mTvRecommendation = null;
         }
         mChannelsPosterPrefetcher.cancel();
-        mChannelsAdapter.release();
     }
 
     /** Handle the update event of the recent channel. */
diff --git a/src/com/android/tv/menu/ChannelsRowAdapter.java b/src/com/android/tv/menu/ChannelsRowAdapter.java
index e6b6103..4a9e476 100644
--- a/src/com/android/tv/menu/ChannelsRowAdapter.java
+++ b/src/com/android/tv/menu/ChannelsRowAdapter.java
@@ -47,7 +47,6 @@
     private final int mMaxCount;
     private final int mMinCount;
     private final ChannelChanger mChannelChanger;
-    private final AccessibilityManager mAccessibilityManager;
 
     private boolean mShowChannelUpDown;
 
@@ -67,9 +66,10 @@
         mMaxCount = maxCount;
         setHasStableIds(true);
         mChannelChanger = (ChannelChanger) (context);
-        mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
-        mShowChannelUpDown = mAccessibilityManager.isEnabled();
-        mAccessibilityManager.addAccessibilityStateChangeListener(this);
+        AccessibilityManager accessibilityManager =
+                context.getSystemService(AccessibilityManager.class);
+        mShowChannelUpDown = accessibilityManager.isEnabled();
+        accessibilityManager.addAccessibilityStateChangeListener(this);
     }
 
     @Override
@@ -316,10 +316,4 @@
         mShowChannelUpDown = enabled;
         update();
     }
-
-    @Override
-    public void release() {
-        mAccessibilityManager.removeAccessibilityStateChangeListener(this);
-        super.release();
-    }
 }
diff --git a/src/com/android/tv/menu/ItemListRowView.java b/src/com/android/tv/menu/ItemListRowView.java
index cc6d23c..7042324 100644
--- a/src/com/android/tv/menu/ItemListRowView.java
+++ b/src/com/android/tv/menu/ItemListRowView.java
@@ -17,9 +17,9 @@
 package com.android.tv.menu;
 
 import android.content.Context;
-import androidx.leanback.widget.HorizontalGridView;
-import androidx.leanback.widget.OnChildSelectedListener;
-import androidx.recyclerview.widget.RecyclerView;
+import android.support.v17.leanback.widget.HorizontalGridView;
+import android.support.v17.leanback.widget.OnChildSelectedListener;
+import android.support.v7.widget.RecyclerView;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.LayoutInflater;
@@ -44,8 +44,6 @@
         void onSelected();
 
         void onDeselected();
-
-        boolean requestFocusWithAccessibility();
     }
 
     private HorizontalGridView mListView;
@@ -116,13 +114,6 @@
         }
     }
 
-    @Override
-    protected void requestChildFocus() {
-        if (mSelectedCard != null) {
-            mSelectedCard.requestFocusWithAccessibility();
-        }
-    }
-
     public abstract static class ItemListAdapter<T>
             extends RecyclerView.Adapter<ItemListAdapter.MyViewHolder> {
         private final MainActivity mMainActivity;
diff --git a/src/com/android/tv/menu/Menu.java b/src/com/android/tv/menu/Menu.java
index 0687441..6bdbf87 100644
--- a/src/com/android/tv/menu/Menu.java
+++ b/src/com/android/tv/menu/Menu.java
@@ -23,7 +23,7 @@
 import android.content.res.Resources;
 import android.support.annotation.IntDef;
 import android.support.annotation.VisibleForTesting;
-import androidx.leanback.widget.HorizontalGridView;
+import android.support.v17.leanback.widget.HorizontalGridView;
 import android.util.Log;
 import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener;
 import com.android.tv.ChannelTuner;
diff --git a/src/com/android/tv/menu/MenuLayoutManager.java b/src/com/android/tv/menu/MenuLayoutManager.java
index 8f95db7..a600f70 100644
--- a/src/com/android/tv/menu/MenuLayoutManager.java
+++ b/src/com/android/tv/menu/MenuLayoutManager.java
@@ -25,15 +25,15 @@
 import android.content.res.Resources;
 import android.graphics.Rect;
 import android.support.annotation.UiThread;
-import androidx.recyclerview.widget.RecyclerView;
+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;
 import android.view.ViewGroup.MarginLayoutParams;
 import android.widget.TextView;
-import androidx.interpolator.view.animation.FastOutLinearInInterpolator;
-import androidx.interpolator.view.animation.FastOutSlowInInterpolator;
-import androidx.interpolator.view.animation.LinearOutSlowInInterpolator;
 import com.android.tv.R;
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.util.Utils;
diff --git a/src/com/android/tv/menu/MenuRow.java b/src/com/android/tv/menu/MenuRow.java
index 0945a0c..8dc12ba 100644
--- a/src/com/android/tv/menu/MenuRow.java
+++ b/src/com/android/tv/menu/MenuRow.java
@@ -31,8 +31,6 @@
 
     private MenuRowView mMenuRowView;
 
-    private boolean mIsReselected = false;
-
     // TODO: Check if the heightResId is really necessary.
     public MenuRow(Context context, Menu menu, int titleResId, int heightResId) {
         this(context, menu, context.getString(titleResId), heightResId);
@@ -102,19 +100,4 @@
     public boolean hideTitleWhenSelected() {
         return false;
     }
-
-    /**
-     * Sets if menu row is reselected.
-     *
-     * @param isReselected {@code true} if row is reselected;
-     * else {@code false}.
-     */
-    public void setIsReselected(boolean isReselected) {
-        mIsReselected = isReselected;
-    }
-
-    /** Returns true if row is reselected. */
-    public boolean isReselected() {
-        return mIsReselected;
-    }
 }
diff --git a/src/com/android/tv/menu/MenuRowFactory.java b/src/com/android/tv/menu/MenuRowFactory.java
index a3837a1..048d725 100644
--- a/src/com/android/tv/menu/MenuRowFactory.java
+++ b/src/com/android/tv/menu/MenuRowFactory.java
@@ -24,7 +24,6 @@
 import com.android.tv.common.customization.CustomAction;
 import com.android.tv.common.customization.CustomizationManager;
 import com.android.tv.ui.TunableTvView;
-import com.android.tv.common.flags.LegacyFlags;
 import java.util.List;
 
 /** A factory class to create menu rows. */
@@ -32,15 +31,12 @@
     private final MainActivity mMainActivity;
     private final TunableTvView mTvView;
     private final CustomizationManager mCustomizationManager;
-    private final LegacyFlags mLegacyFlags;
 
     /** A constructor. */
-    public MenuRowFactory(
-            MainActivity mainActivity, TunableTvView tvView, LegacyFlags mLegacyFlags) {
+    public MenuRowFactory(MainActivity mainActivity, TunableTvView tvView) {
         mMainActivity = mainActivity;
         mTvView = tvView;
         mCustomizationManager = new CustomizationManager(mainActivity);
-        this.mLegacyFlags = mLegacyFlags;
         mCustomizationManager.initialize();
     }
 
@@ -64,8 +60,7 @@
             return new TvOptionsRow(
                     mMainActivity,
                     menu,
-                    mCustomizationManager.getCustomActions(CustomizationManager.ID_OPTIONS_ROW),
-                    mLegacyFlags);
+                    mCustomizationManager.getCustomActions(CustomizationManager.ID_OPTIONS_ROW));
         }
         return null;
     }
@@ -75,17 +70,13 @@
         /** The ID of the row. */
         public static final String ID = TvOptionsRow.class.getName();
 
-        private TvOptionsRow(
-                Context context,
-                Menu menu,
-                List<CustomAction> customActions,
-                LegacyFlags legacyFlags) {
+        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, legacyFlags));
+                    new TvOptionsRowAdapter(context, customActions));
         }
     }
 
diff --git a/src/com/android/tv/menu/MenuRowView.java b/src/com/android/tv/menu/MenuRowView.java
index e09a4ef..a064f35 100644
--- a/src/com/android/tv/menu/MenuRowView.java
+++ b/src/com/android/tv/menu/MenuRowView.java
@@ -25,7 +25,6 @@
 import android.util.TypedValue;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.accessibility.AccessibilityEvent;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 import com.android.tv.R;
@@ -90,18 +89,6 @@
         float textSizeDeselected =
                 res.getDimensionPixelSize(R.dimen.menu_row_title_text_size_deselected);
         mTitleViewScaleSelected = textSizeSelected / textSizeDeselected;
-        this.setAccessibilityDelegate(
-                new AccessibilityDelegate() {
-                    @Override
-                    public void sendAccessibilityEvent(View host, int eventType) {
-                        super.sendAccessibilityEvent(host, eventType);
-                        if (eventType == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED &&
-                                !mRow.isReselected()) {
-                            requestChildFocus();
-                        }
-                    }
-                }
-        );
     }
 
     @Override
@@ -190,9 +177,6 @@
         mLastFocusView = v;
     }
 
-    /** Subclasses should implement this to request focus on child. */
-    protected abstract void requestChildFocus();
-
     /**
      * Called when the focus of a child view is changed. The inherited class should override this
      * method instead of calling {@link
diff --git a/src/com/android/tv/menu/MenuView.java b/src/com/android/tv/menu/MenuView.java
index add4a77..f5fec00 100644
--- a/src/com/android/tv/menu/MenuView.java
+++ b/src/com/android/tv/menu/MenuView.java
@@ -250,42 +250,41 @@
         // The bounds of the views move and overlap with each other during the animation. In this
         // situation, the framework can't perform the correct focus navigation. So the menu view
         // should search by itself.
-        if (direction == View.FOCUS_UP || direction == View.FOCUS_DOWN) {
-            return getUpDownFocus(focused, direction);
+        if (direction == View.FOCUS_UP) {
+            View newView = super.focusSearch(focused, direction);
+            MenuRowView oldfocusedParent = getParentMenuRowView(focused);
+            MenuRowView newFocusedParent = getParentMenuRowView(newView);
+            int selectedPosition = mLayoutManager.getSelectedPosition();
+            if (newFocusedParent != oldfocusedParent) {
+                // The focus leaves from the current menu row view.
+                for (int i = selectedPosition - 1; i >= 0; --i) {
+                    MenuRowView view = mMenuRowViews.get(i);
+                    if (view.getVisibility() == View.VISIBLE) {
+                        return view;
+                    }
+                }
+            }
+            return newView;
+        } else if (direction == View.FOCUS_DOWN) {
+            View newView = super.focusSearch(focused, direction);
+            MenuRowView oldfocusedParent = getParentMenuRowView(focused);
+            MenuRowView newFocusedParent = getParentMenuRowView(newView);
+            int selectedPosition = mLayoutManager.getSelectedPosition();
+            if (newFocusedParent != oldfocusedParent) {
+                // The focus leaves from the current menu row view.
+                int count = mMenuRowViews.size();
+                for (int i = selectedPosition + 1; i < count; ++i) {
+                    MenuRowView view = mMenuRowViews.get(i);
+                    if (view.getVisibility() == View.VISIBLE) {
+                        return view;
+                    }
+                }
+            }
+            return newView;
         }
         return super.focusSearch(focused, direction);
     }
 
-    private View getUpDownFocus(View focused, int direction) {
-        View newView = super.focusSearch(focused, direction);
-        MenuRowView oldfocusedParent = getParentMenuRowView(focused);
-        MenuRowView newFocusedParent = getParentMenuRowView(newView);
-        int selectedPosition = mLayoutManager.getSelectedPosition();
-        int start, delta;
-        if (direction == View.FOCUS_UP) {
-            start = selectedPosition - 1;
-            delta = -1;
-        } else {
-            start = selectedPosition + 1;
-            delta = 1;
-        }
-        if (newFocusedParent != oldfocusedParent) {
-            // The focus leaves from the current menu row view.
-            int count = mMenuRowViews.size();
-            int i = start;
-            while (i < count && i >= 0) {
-                MenuRowView view = mMenuRowViews.get(i);
-                if (view.getVisibility() == View.VISIBLE) {
-                    mMenuRows.get(i).setIsReselected(false);
-                    return view;
-                }
-                i += delta;
-            }
-        }
-        mMenuRows.get(selectedPosition).setIsReselected(true);
-        return newView;
-    }
-
     private MenuRowView getParentMenuRowView(View view) {
         if (view == null) {
             return null;
diff --git a/src/com/android/tv/menu/PlayControlsButton.java b/src/com/android/tv/menu/PlayControlsButton.java
index 1b85d63..ac3292a 100644
--- a/src/com/android/tv/menu/PlayControlsButton.java
+++ b/src/com/android/tv/menu/PlayControlsButton.java
@@ -22,7 +22,6 @@
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.View;
-import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.TextView;
@@ -147,11 +146,4 @@
         mIcon.setAlpha(enabled ? ALPHA_ENABLED : ALPHA_DISABLED);
         mLabel.setEnabled(enabled);
     }
-
-    /** Request focus and accessibility focus to the button */
-    public boolean requestFocusWithAccessibility() {
-        return mButton.requestFocus() &&
-                mButton.performAccessibilityAction(
-                        AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
-    }
 }
diff --git a/src/com/android/tv/menu/PlayControlsRowView.java b/src/com/android/tv/menu/PlayControlsRowView.java
index 5dde3be..0ce74ae 100644
--- a/src/com/android/tv/menu/PlayControlsRowView.java
+++ b/src/com/android/tv/menu/PlayControlsRowView.java
@@ -24,7 +24,6 @@
 import android.view.View;
 import android.widget.TextView;
 import android.widget.Toast;
-
 import com.android.tv.MainActivity;
 import com.android.tv.R;
 import com.android.tv.TimeShiftManager;
@@ -32,8 +31,8 @@
 import com.android.tv.TvSingletons;
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.common.feature.CommonFeatures;
+import com.android.tv.data.Program;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
 import com.android.tv.dialog.HalfSizedDialogFragment;
 import com.android.tv.dvr.DvrDataManager;
 import com.android.tv.dvr.DvrDataManager.OnDvrScheduleLoadFinishedListener;
@@ -488,11 +487,6 @@
         }
     }
 
-    @Override
-    protected void requestChildFocus() {
-        mPlayPauseButton.requestFocusWithAccessibility();
-    }
-
     /** Updates the view contents. It is called from the PlayControlsRow. */
     public void update() {
         updateAll(false);
diff --git a/src/com/android/tv/menu/TvOptionsRowAdapter.java b/src/com/android/tv/menu/TvOptionsRowAdapter.java
index 418560a..fe52b25 100644
--- a/src/com/android/tv/menu/TvOptionsRowAdapter.java
+++ b/src/com/android/tv/menu/TvOptionsRowAdapter.java
@@ -19,8 +19,8 @@
 import android.content.Context;
 import android.media.tv.TvTrackInfo;
 import com.android.tv.TvOptionsManager;
-import com.android.tv.common.BuildConfig;
 import com.android.tv.common.customization.CustomAction;
+import com.android.tv.common.util.CommonUtils;
 import com.android.tv.data.DisplayMode;
 import com.android.tv.features.TvFeatures;
 import com.android.tv.ui.TvViewUiManager;
@@ -28,7 +28,6 @@
 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.common.flags.LegacyFlags;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -36,12 +35,8 @@
  * An adapter of options.
  */
 public class TvOptionsRowAdapter extends CustomizableOptionsRowAdapter {
-    private final LegacyFlags mLegacyFlags;
-
-    public TvOptionsRowAdapter(
-            Context context, List<CustomAction> customActions, LegacyFlags mLegacyFlags) {
+    public TvOptionsRowAdapter(Context context, List<CustomAction> customActions) {
         super(context, customActions);
-        this.mLegacyFlags = mLegacyFlags;
     }
 
     @Override
@@ -54,7 +49,7 @@
         }
         actionList.add(MenuAction.SELECT_AUDIO_LANGUAGE_ACTION);
         actionList.add(MenuAction.MORE_CHANNELS_ACTION);
-        if (BuildConfig.ENG || mLegacyFlags.enableDeveloperFeatures()) {
+        if (CommonUtils.isDeveloper()) {
             actionList.add(MenuAction.DEV_ACTION);
         }
         actionList.add(MenuAction.SETTINGS_ACTION);
diff --git a/src/com/android/tv/modules/TvApplicationModule.java b/src/com/android/tv/modules/TvApplicationModule.java
index 99753d1..45383ae 100644
--- a/src/com/android/tv/modules/TvApplicationModule.java
+++ b/src/com/android/tv/modules/TvApplicationModule.java
@@ -16,101 +16,43 @@
 package com.android.tv.modules;
 
 import android.content.Context;
-
 import com.android.tv.MainActivity;
-import com.android.tv.SetupPassthroughActivity;
 import com.android.tv.TvApplication;
-import com.android.tv.common.buildtype.BuildTypeModule;
 import com.android.tv.common.concurrent.NamedThreadFactory;
 import com.android.tv.common.dagger.ApplicationModule;
 import com.android.tv.common.dagger.annotations.ApplicationContext;
-import com.android.tv.data.ChannelDataManager;
-import com.android.tv.data.ChannelDataManagerFactory;
-import com.android.tv.data.epg.EpgFetchService;
-import com.android.tv.data.epg.EpgFetcher;
-import com.android.tv.data.epg.EpgFetcherImpl;
-import com.android.tv.dialog.PinDialogFragment;
-import com.android.tv.dvr.DvrDataManager;
-import com.android.tv.dvr.DvrDataManagerImpl;
-import com.android.tv.dvr.WritableDvrDataManager;
-import com.android.tv.dvr.ui.playback.DvrPlaybackActivity;
 import com.android.tv.onboarding.OnboardingActivity;
-import com.android.tv.onboarding.SetupSourcesFragment;
-import com.android.tv.setup.SystemSetupActivity;
-import com.android.tv.ui.DetailsActivity;
 import com.android.tv.util.AsyncDbTask;
 import com.android.tv.util.TvInputManagerHelper;
-
-import dagger.Binds;
 import dagger.Module;
 import dagger.Provides;
-import dagger.android.ContributesAndroidInjector;
-
-import com.android.tv.common.flags.LegacyFlags;
-
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
-
 import javax.inject.Singleton;
 
 /** Dagger module for {@link TvApplication}. */
 @Module(
         includes = {
             ApplicationModule.class,
-            BuildTypeModule.class,
-            DetailsActivity.Module.class,
-            DvrPlaybackActivity.Module.class,
-            MainActivity.Module.class,
-            OnboardingActivity.Module.class,
-            SetupPassthroughActivity.Module.class,
-            SetupSourcesFragment.ContentFragment.Module.class,
-            SystemSetupActivity.Module.class,
             TvSingletonsModule.class,
+            MainActivity.Module.class,
+            OnboardingActivity.Module.class
         })
-public abstract class TvApplicationModule {
+public class TvApplicationModule {
     private static final NamedThreadFactory THREAD_FACTORY = new NamedThreadFactory("tv-app-db");
 
     @Provides
     @AsyncDbTask.DbExecutor
     @Singleton
-    static Executor providesDbExecutor() {
+    Executor providesDbExecutor() {
         return Executors.newSingleThreadExecutor(THREAD_FACTORY);
     }
 
     @Provides
     @Singleton
-    static TvInputManagerHelper providesTvInputManagerHelper(
-            @ApplicationContext Context context, LegacyFlags legacyFlags) {
-        TvInputManagerHelper tvInputManagerHelper = new TvInputManagerHelper(context, legacyFlags);
+    TvInputManagerHelper providesTvInputManagerHelper(@ApplicationContext Context context) {
+        TvInputManagerHelper tvInputManagerHelper = new TvInputManagerHelper(context);
         tvInputManagerHelper.start();
-        // Since this is injected as a Lazy in the application start is delayed.
         return tvInputManagerHelper;
     }
-
-    @Provides
-    @Singleton
-    static ChannelDataManager providesChannelDataManager(ChannelDataManagerFactory factory) {
-        ChannelDataManager channelDataManager = factory.create();
-        channelDataManager.start();
-        // Since this is injected as a Lazy in the application start is delayed.
-        return channelDataManager;
-    }
-
-    @Binds
-    @Singleton
-    abstract DvrDataManager providesDvrDataManager(DvrDataManagerImpl impl);
-
-    @Binds
-    @Singleton
-    abstract WritableDvrDataManager providesWritableDvrDataManager(DvrDataManagerImpl impl);
-
-    @Binds
-    @Singleton
-    abstract EpgFetcher epgFetcher(EpgFetcherImpl impl);
-
-    @ContributesAndroidInjector
-    abstract PinDialogFragment contributesPinDialogFragment();
-
-    @ContributesAndroidInjector
-    abstract EpgFetchService contributesEpgFetchService();
 }
diff --git a/src/com/android/tv/modules/TvSingletonsModule.java b/src/com/android/tv/modules/TvSingletonsModule.java
index f8d10fd..f998c08 100644
--- a/src/com/android/tv/modules/TvSingletonsModule.java
+++ b/src/com/android/tv/modules/TvSingletonsModule.java
@@ -16,9 +16,8 @@
 package com.android.tv.modules;
 
 import com.android.tv.TvSingletons;
+import com.android.tv.data.ChannelDataManager;
 import com.android.tv.data.ProgramDataManager;
-import com.android.tv.dvr.DvrWatchedPositionManager;
-
 import dagger.Module;
 import dagger.Provides;
 
@@ -37,8 +36,8 @@
     }
 
     @Provides
-    DvrWatchedPositionManager providesDvrWatchedPositionManager() {
-        return mTvSingletons.getDvrWatchedPositionManager();
+    ChannelDataManager providesChannelDataManager() {
+        return mTvSingletons.getChannelDataManager();
     }
 
     @Provides
diff --git a/src/com/android/tv/onboarding/OnboardingActivity.java b/src/com/android/tv/onboarding/OnboardingActivity.java
index 1739e5a..776ae66 100644
--- a/src/com/android/tv/onboarding/OnboardingActivity.java
+++ b/src/com/android/tv/onboarding/OnboardingActivity.java
@@ -88,7 +88,7 @@
         TvSingletons singletons = TvSingletons.getSingletons(this);
         mInputManager = singletons.getTvInputManagerHelper();
         if (PermissionUtils.hasAccessAllEpg(this) || PermissionUtils.hasReadTvListings(this)) {
-            // Make the channels of the new inputs which have been setup outside TV app
+            // Make the channels of the new inputs which have been setup outside Live TV
             // browsable.
             if (mChannelDataManager.isDbLoadFinished()) {
                 mSetupUtils.markNewChannelsBrowsable();
@@ -187,7 +187,7 @@
                             }
                             // Even though other app can handle the intent, the setup launched by
                             // Live
-                            // channels should go through TV app SetupPassthroughActivity.
+                            // channels should go through Live channels SetupPassthroughActivity.
                             intent.setComponent(
                                     new ComponentName(this, SetupPassthroughActivity.class));
                             try {
diff --git a/src/com/android/tv/onboarding/SetupSourcesFragment.java b/src/com/android/tv/onboarding/SetupSourcesFragment.java
index b54d1bc..3566c9c 100644
--- a/src/com/android/tv/onboarding/SetupSourcesFragment.java
+++ b/src/com/android/tv/onboarding/SetupSourcesFragment.java
@@ -16,44 +16,33 @@
 
 package com.android.tv.onboarding;
 
-import android.app.Activity;
+import android.content.Context;
 import android.graphics.Typeface;
 import android.media.tv.TvInputInfo;
 import android.media.tv.TvInputManager.TvInputCallback;
 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.support.v17.leanback.widget.VerticalGridView;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.TextView;
-
-import androidx.leanback.widget.GuidanceStylist.Guidance;
-import androidx.leanback.widget.GuidedAction;
-import androidx.leanback.widget.GuidedActionsStylist;
-import androidx.leanback.widget.VerticalGridView;
-
 import com.android.tv.R;
 import com.android.tv.TvSingletons;
 import com.android.tv.common.ui.setup.SetupGuidedStepFragment;
 import com.android.tv.common.ui.setup.SetupMultiPaneFragment;
 import com.android.tv.data.ChannelDataManager;
 import com.android.tv.data.TvInputNewComparator;
-import com.android.tv.tunerinputcontroller.BuiltInTunerManager;
 import com.android.tv.ui.GuidedActionsStylistWithDivider;
 import com.android.tv.util.SetupUtils;
 import com.android.tv.util.TvInputManagerHelper;
-
-import com.google.common.base.Optional;
-
-import dagger.android.AndroidInjection;
-import dagger.android.ContributesAndroidInjector;
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
-import javax.inject.Inject;
-
 /** A fragment for channel source info/setup. */
 public class SetupSourcesFragment extends SetupMultiPaneFragment {
     /** The action category for the actions which is fired from this fragment. */
@@ -117,10 +106,9 @@
         private static final int PENDING_ACTION_INPUT_CHANGED = 1;
         private static final int PENDING_ACTION_CHANNEL_CHANGED = 2;
 
-        @Inject TvInputManagerHelper mInputManager;
-        @Inject ChannelDataManager mChannelDataManager;
-        @Inject SetupUtils mSetupUtils;
-        @Inject Optional<BuiltInTunerManager> mBuiltInTunerManagerOptional;
+        private TvInputManagerHelper mInputManager;
+        private ChannelDataManager mChannelDataManager;
+        private SetupUtils mSetupUtils;
         private List<TvInputInfo> mInputs;
         private int mKnownInputStartIndex;
         private int mDoneInputStartIndex;
@@ -199,38 +187,37 @@
 
         @Override
         public void onCreate(Bundle savedInstanceState) {
-            super.onCreate(savedInstanceState);
-            mParentFragment = (SetupSourcesFragment) getParentFragment();
-        }
-
-        @Override
-        public void onAttach(Activity activity) {
-            AndroidInjection.inject(this);
-            super.onAttach(activity);
+            Context context = getActivity();
+            TvSingletons singletons = TvSingletons.getSingletons(context);
+            mInputManager = singletons.getTvInputManagerHelper();
+            mChannelDataManager = singletons.getChannelDataManager();
+            mSetupUtils = singletons.getSetupUtils();
             buildInputs();
             mInputManager.addCallback(mInputCallback);
             mChannelDataManager.addListener(mChannelDataManagerListener);
+            super.onCreate(savedInstanceState);
             mParentFragment = (SetupSourcesFragment) getParentFragment();
-            if (mBuiltInTunerManagerOptional.isPresent()) {
-                mBuiltInTunerManagerOptional
+            if (singletons.getBuiltInTunerManager().isPresent()) {
+                singletons
+                        .getBuiltInTunerManager()
                         .get()
                         .getTunerInputController()
-                        .executeNetworkTunerDiscoveryAsyncTask(activity);
+                        .executeNetworkTunerDiscoveryAsyncTask(getContext());
             }
         }
 
         @Override
-        public void onDetach() {
+        public void onDestroy() {
+            super.onDestroy();
             mChannelDataManager.removeListener(mChannelDataManagerListener);
             mInputManager.removeCallback(mInputCallback);
-            super.onDetach();
         }
 
         @NonNull
         @Override
         public Guidance onCreateGuidance(Bundle savedInstanceState) {
             String title = getString(R.string.setup_sources_text);
-            String description = getString(R.string.setup_sources_description2);
+            String description = getString(R.string.setup_sources_description);
             return new Guidance(title, description, null, null);
         }
 
@@ -417,13 +404,5 @@
                 setAccessibilityDelegate(vh, action);
             }
         }
-        /**
-         * Exports {@link ContentFragment} for Dagger codegen to create the appropriate injector.
-         */
-        @dagger.Module
-        public abstract static class Module {
-            @ContributesAndroidInjector
-            abstract ContentFragment contributesContentFragment();
-        }
     }
 }
diff --git a/src/com/android/tv/onboarding/WelcomeFragment.java b/src/com/android/tv/onboarding/WelcomeFragment.java
index 667da05..8c119a8 100644
--- a/src/com/android/tv/onboarding/WelcomeFragment.java
+++ b/src/com/android/tv/onboarding/WelcomeFragment.java
@@ -25,7 +25,7 @@
 import android.content.Context;
 import android.os.Bundle;
 import android.support.annotation.Nullable;
-import androidx.leanback.app.OnboardingFragment;
+import android.support.v17.leanback.app.OnboardingFragment;
 import android.text.Editable;
 import android.text.TextWatcher;
 import android.view.Gravity;
@@ -621,9 +621,9 @@
             LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
         View view = super.onCreateView(inflater, container, savedInstanceState);
         setLogoResourceId(R.drawable.splash_logo);
-        mTitleView = view.findViewById(androidx.leanback.R.id.title);
-        mPagingIndicator = view.findViewById(androidx.leanback.R.id.page_indicator);
-        mStartButton = view.findViewById(androidx.leanback.R.id.button_start);
+        mTitleView = view.findViewById(android.support.v17.leanback.R.id.title);
+        mPagingIndicator = view.findViewById(android.support.v17.leanback.R.id.page_indicator);
+        mStartButton = view.findViewById(android.support.v17.leanback.R.id.button_start);
 
         mStartButton.setAccessibilityDelegate(
                 new AccessibilityDelegate() {
diff --git a/src/com/android/tv/parental/ContentRatingsManager.java b/src/com/android/tv/parental/ContentRatingsManager.java
index 174039b..32a1325 100644
--- a/src/com/android/tv/parental/ContentRatingsManager.java
+++ b/src/com/android/tv/parental/ContentRatingsManager.java
@@ -22,7 +22,6 @@
 import android.support.annotation.Nullable;
 import android.text.TextUtils;
 import com.android.tv.R;
-import com.android.tv.common.util.PermissionUtils;
 import com.android.tv.parental.ContentRatingSystem.Rating;
 import com.android.tv.parental.ContentRatingSystem.SubRating;
 import com.android.tv.util.TvInputManagerHelper;
@@ -43,14 +42,13 @@
 
     public void update() {
         mContentRatingSystems.clear();
-        if (PermissionUtils.hasReadContetnRatingSystem(mContext)) {
-            ContentRatingsParser parser = new ContentRatingsParser(mContext);
-            List<TvContentRatingSystemInfo> infos = mTvInputManager.getTvContentRatingSystemList();
-            for (TvContentRatingSystemInfo info : infos) {
-                List<ContentRatingSystem> list = parser.parse(info);
-                if (list != null) {
-                    mContentRatingSystems.addAll(list);
-                }
+        ContentRatingsParser parser = new ContentRatingsParser(mContext);
+
+        List<TvContentRatingSystemInfo> infos = mTvInputManager.getTvContentRatingSystemList();
+        for (TvContentRatingSystemInfo info : infos) {
+            List<ContentRatingSystem> list = parser.parse(info);
+            if (list != null) {
+                mContentRatingSystems.addAll(list);
             }
         }
     }
diff --git a/src/com/android/tv/parental/ParentalControlSettings.java b/src/com/android/tv/parental/ParentalControlSettings.java
index 9990ae3..b41b160 100644
--- a/src/com/android/tv/parental/ParentalControlSettings.java
+++ b/src/com/android/tv/parental/ParentalControlSettings.java
@@ -19,12 +19,12 @@
 import android.content.Context;
 import android.media.tv.TvContentRating;
 import android.media.tv.TvInputManager;
+import com.android.tv.common.experiments.Experiments;
 import com.android.tv.parental.ContentRatingSystem.Rating;
 import com.android.tv.parental.ContentRatingSystem.SubRating;
 import com.android.tv.util.TvSettings;
 import com.android.tv.util.TvSettings.ContentRatingLevel;
 import com.google.common.collect.ImmutableList;
-import com.android.tv.common.flags.LegacyFlags;
 import java.util.HashSet;
 import java.util.Set;
 
@@ -40,16 +40,14 @@
 
     private final Context mContext;
     private final TvInputManager mTvInputManager;
-    private final LegacyFlags mLegacyFlags;
 
     // mRatings is expected to be synchronized with mTvInputManager.getBlockedRatings().
     private Set<TvContentRating> mRatings;
     private Set<TvContentRating> mCustomRatings;
 
-    public ParentalControlSettings(Context context, LegacyFlags legacyFlags) {
+    public ParentalControlSettings(Context context) {
         mContext = context;
         mTvInputManager = (TvInputManager) mContext.getSystemService(Context.TV_INPUT_SERVICE);
-        mLegacyFlags = legacyFlags;
     }
 
     public boolean isParentalControlsEnabled() {
@@ -132,7 +130,7 @@
         } else {
             mRatings = ContentRatingLevelPolicy.getRatingsForLevel(this, manager, level);
             if (level != TvSettings.CONTENT_RATING_LEVEL_NONE
-                    && mLegacyFlags.enableUnratedContentSettings()) {
+                    && 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);
             }
diff --git a/src/com/android/tv/perf/PerformanceMonitor.java b/src/com/android/tv/perf/PerformanceMonitor.java
index 30197c7..b1ae759 100644
--- a/src/com/android/tv/perf/PerformanceMonitor.java
+++ b/src/com/android/tv/perf/PerformanceMonitor.java
@@ -96,14 +96,4 @@
      * @return true if the activity is available to start
      */
     boolean startPerformanceMonitorEventDebugActivity(Context context);
-
-    /**
-     * Initialize crash monitoring for an app by wrapping the default {@link
-     * Thread.UncaughtExceptionHandler} with a handler that can report crashes to the performance
-     * montitor and then delegate the handling of the UncaughtException to the original default
-     * {@link Thread.UncaughtExceptionHandler}.
-     *
-     * <p>Note: This will override the current {@link Thread.UncaughtExceptionHandler}.
-     */
-    void startCrashMonitor();
 }
diff --git a/src/com/android/tv/perf/PerformanceMonitorManager.java b/src/com/android/tv/perf/PerformanceMonitorManager.java
new file mode 100644
index 0000000..db6667d
--- /dev/null
+++ b/src/com/android/tv/perf/PerformanceMonitorManager.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2018 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;
+
+/** Manages the initialization of Performance Monitoring. */
+public interface PerformanceMonitorManager {
+
+    /**
+     * Initializes the {@link com.android.tv.perf.PerformanceMonitor}.
+     *
+     * <p>This should only be called once.
+     */
+    PerformanceMonitor initialize(Application app);
+
+    /**
+     * Returns a lightweight object to help measure both cold and warm startup latency.
+     *
+     * <p>This method is idempotent and lightweight. It can be called multiple times and does not
+     * need to be cached.
+     */
+    StartupMeasure getStartupMeasure();
+}
diff --git a/src/com/android/tv/perf/PerformanceMonitorManagerFactory.java b/src/com/android/tv/perf/PerformanceMonitorManagerFactory.java
new file mode 100644
index 0000000..fe3ea14
--- /dev/null
+++ b/src/com/android/tv/perf/PerformanceMonitorManagerFactory.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 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 com.android.tv.perf.stub.StubPerformanceMonitorManager;
+import javax.inject.Inject;
+
+public final class PerformanceMonitorManagerFactory {
+    private static final PerformanceMonitorManagerFactory INSTANCE =
+            new PerformanceMonitorManagerFactory();
+
+    @Inject
+    public PerformanceMonitorManagerFactory() {}
+
+    public static PerformanceMonitorManager create() {
+        return INSTANCE.get();
+    }
+
+    public PerformanceMonitorManager get() {
+        return new StubPerformanceMonitorManager();
+    }
+}
diff --git a/src/com/android/tv/perf/StartupMeasure.java b/src/com/android/tv/perf/StartupMeasure.java
index c7fa50f..5cf183c 100644
--- a/src/com/android/tv/perf/StartupMeasure.java
+++ b/src/com/android/tv/perf/StartupMeasure.java
@@ -19,16 +19,8 @@
 import android.app.Application;
 
 /**
- * Measures App startup.
- *
- * <p>This interface is lightweight to help measure both cold and warm startup latency.
- * Implementations must not throw any Exception.
- *
- * <p>Because this class needs to be used in static initialization blocks, it can not be injected
- * via dagger.
- *
- * <p>Creating implementations of this interface must be idempotent and lightweight. It does not
- * need to be cached.
+ * Measures App startup. This interface is lightweight to help measure both cold and warm startup
+ * latency. Implementations must not throw any Exception.
  */
 public interface StartupMeasure {
 
diff --git a/src/com/android/tv/perf/StartupMeasureFactory.java b/src/com/android/tv/perf/StartupMeasureFactory.java
deleted file mode 100644
index a99c88a..0000000
--- a/src/com/android/tv/perf/StartupMeasureFactory.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2019 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 com.android.tv.perf.stub.StubStartupMeasure;
-
-import com.google.common.base.Supplier;
-import java.lang.Override;
-import javax.inject.Inject;
-
-/** Factory for {@link StartupMeasure}.
- *
- * <p>Hardcoded to {@link StubStartupMeasure}.
- */
-public final class StartupMeasureFactory implements Supplier<StartupMeasure> {
-    private static final StartupMeasureFactory INSTANCE = new StartupMeasureFactory();
-
-    @Inject
-    public StartupMeasureFactory() {}
-
-    public static StartupMeasure create() {
-        return INSTANCE.get();
-    }
-
-    @Override
-    public StartupMeasure get() {
-        return new StubStartupMeasure();
-    }
-}
diff --git a/src/com/android/tv/perf/stub/StubPerformanceMonitor.java b/src/com/android/tv/perf/stub/StubPerformanceMonitor.java
index ac3dc25..80c2f6c 100644
--- a/src/com/android/tv/perf/stub/StubPerformanceMonitor.java
+++ b/src/com/android/tv/perf/stub/StubPerformanceMonitor.java
@@ -56,6 +56,7 @@
         return false;
     }
 
-    @Override
-    public void startCrashMonitor() {}
+    public static TimerEvent startBootstrapTimer() {
+        return new TimerEvent() {};
+    }
 }
diff --git a/src/com/android/tv/perf/stub/StubPerformanceMonitorManager.java b/src/com/android/tv/perf/stub/StubPerformanceMonitorManager.java
new file mode 100644
index 0000000..0c26815
--- /dev/null
+++ b/src/com/android/tv/perf/stub/StubPerformanceMonitorManager.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2018 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.stub;
+
+import android.app.Application;
+import com.android.tv.perf.PerformanceMonitor;
+import com.android.tv.perf.PerformanceMonitorManager;
+import com.android.tv.perf.StartupMeasure;
+
+/** Manages a stub implementation of Performance Monitoring. */
+public class StubPerformanceMonitorManager implements PerformanceMonitorManager {
+
+    @Override
+    public PerformanceMonitor initialize(Application app) {
+        return new StubPerformanceMonitor();
+    }
+
+    @Override
+    public StartupMeasure getStartupMeasure() {
+        return new StubStartupMeasure();
+    }
+}
diff --git a/src/com/android/tv/receiver/AudioCapabilitiesReceiver.java b/src/com/android/tv/receiver/AudioCapabilitiesReceiver.java
index 5fa7606..3fb6624 100644
--- a/src/com/android/tv/receiver/AudioCapabilitiesReceiver.java
+++ b/src/com/android/tv/receiver/AudioCapabilitiesReceiver.java
@@ -42,7 +42,7 @@
     // AC3 capabilities stat is sent to Google Analytics just once in order to avoid
     // duplicated stat reports since it doesn't change over time in most cases.
     // Increase this revision when we should force the stat to be sent again.
-    // TODO: Consider using custom metrics.
+    // TODO: Consier using custom metrics.
     private static final int REPORT_REVISION = 1;
 
     private final Context mContext;
diff --git a/src/com/android/tv/receiver/PackageIntentsReceiver.java b/src/com/android/tv/receiver/PackageIntentsReceiver.java
index 7ff67b5..5bc6d72 100644
--- a/src/com/android/tv/receiver/PackageIntentsReceiver.java
+++ b/src/com/android/tv/receiver/PackageIntentsReceiver.java
@@ -23,7 +23,9 @@
 import android.util.Log;
 import com.android.tv.Starter;
 import com.android.tv.TvSingletons;
+import com.android.tv.features.TvFeatures;
 import com.android.tv.util.Partner;
+import com.google.android.tv.partner.support.EpgContract;
 
 /** A class for handling the broadcast intents from PackageManager. */
 public class PackageIntentsReceiver extends BroadcastReceiver {
diff --git a/src/com/android/tv/recommendation/ChannelPreviewUpdater.java b/src/com/android/tv/recommendation/ChannelPreviewUpdater.java
index 61ebb2d..2590a33 100644
--- a/src/com/android/tv/recommendation/ChannelPreviewUpdater.java
+++ b/src/com/android/tv/recommendation/ChannelPreviewUpdater.java
@@ -27,18 +27,15 @@
 import android.support.annotation.RequiresApi;
 import android.text.TextUtils;
 import android.util.Log;
-
 import androidx.tvprovider.media.tv.TvContractCompat;
-
 import com.android.tv.Starter;
 import com.android.tv.TvSingletons;
 import com.android.tv.data.PreviewDataManager;
 import com.android.tv.data.PreviewProgramContent;
+import com.android.tv.data.Program;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.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;
diff --git a/src/com/android/tv/recommendation/ChannelRecord.java b/src/com/android/tv/recommendation/ChannelRecord.java
index f047aac..c7a7cb3 100644
--- a/src/com/android/tv/recommendation/ChannelRecord.java
+++ b/src/com/android/tv/recommendation/ChannelRecord.java
@@ -19,12 +19,10 @@
 import android.content.Context;
 import android.support.annotation.GuardedBy;
 import android.support.annotation.VisibleForTesting;
-
 import com.android.tv.TvSingletons;
+import com.android.tv.data.Program;
 import com.android.tv.data.ProgramDataManager;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
-
 import java.util.ArrayDeque;
 import java.util.Deque;
 
diff --git a/src/com/android/tv/recommendation/NotificationService.java b/src/com/android/tv/recommendation/NotificationService.java
index 1652bd7..f40a086 100644
--- a/src/com/android/tv/recommendation/NotificationService.java
+++ b/src/com/android/tv/recommendation/NotificationService.java
@@ -40,21 +40,19 @@
 import android.util.Log;
 import android.util.SparseLongArray;
 import android.view.View;
-
 import com.android.tv.MainActivityWrapper.OnCurrentChannelChangeListener;
 import com.android.tv.R;
 import com.android.tv.Starter;
 import com.android.tv.TvSingletons;
 import com.android.tv.common.CommonConstants;
 import com.android.tv.common.WeakHandler;
+import com.android.tv.data.Program;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
 import com.android.tv.util.TvInputManagerHelper;
 import com.android.tv.util.Utils;
 import com.android.tv.util.images.BitmapUtils;
 import com.android.tv.util.images.BitmapUtils.ScaledBitmapInfo;
 import com.android.tv.util.images.ImageLoader;
-
 import java.util.ArrayList;
 import java.util.List;
 
diff --git a/src/com/android/tv/recommendation/RecommendationDataManager.java b/src/com/android/tv/recommendation/RecommendationDataManager.java
index e254ba5..fc20031 100644
--- a/src/com/android/tv/recommendation/RecommendationDataManager.java
+++ b/src/com/android/tv/recommendation/RecommendationDataManager.java
@@ -34,17 +34,14 @@
 import android.support.annotation.Nullable;
 import android.support.annotation.WorkerThread;
 import android.util.Log;
-
 import com.android.tv.TvSingletons;
 import com.android.tv.common.WeakHandler;
 import com.android.tv.common.util.PermissionUtils;
 import com.android.tv.data.ChannelDataManager;
-import com.android.tv.data.ProgramImpl;
+import com.android.tv.data.Program;
 import com.android.tv.data.WatchedHistoryManager;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
 import com.android.tv.util.TvUriMatcher;
-
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -235,9 +232,6 @@
 
     @MainThread
     private void stop() {
-        if (mWatchedHistoryManager != null) {
-            mWatchedHistoryManager.setListener(null);
-        }
         for (int what = MSG_FIRST; what <= MSG_LAST; ++what) {
             mHandler.removeMessages(what);
         }
@@ -365,7 +359,7 @@
             WatchedHistoryManager.WatchedRecord watchedRecord) {
         long endTime = watchedRecord.watchedStartTime + watchedRecord.duration;
         Program program =
-                new ProgramImpl.Builder()
+                new Program.Builder()
                         .setChannelId(watchedRecord.channelId)
                         .setTitle("")
                         .setStartTimeUtcMillis(watchedRecord.watchedStartTime)
@@ -417,7 +411,7 @@
         }
 
         Program program =
-                new ProgramImpl.Builder()
+                new Program.Builder()
                         .setChannelId(cursor.getLong(mIndexWatchChannelId))
                         .setTitle(cursor.getString(mIndexProgramTitle))
                         .setStartTimeUtcMillis(cursor.getLong(mIndexProgramStartTime))
diff --git a/src/com/android/tv/recommendation/Recommender.java b/src/com/android/tv/recommendation/Recommender.java
index a8535a4..f350799 100644
--- a/src/com/android/tv/recommendation/Recommender.java
+++ b/src/com/android/tv/recommendation/Recommender.java
@@ -20,9 +20,7 @@
 import android.support.annotation.VisibleForTesting;
 import android.util.Log;
 import android.util.Pair;
-
 import com.android.tv.data.api.Channel;
-
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -129,7 +127,7 @@
                 }
             }
             if (!mIncludeRecommendedOnly || maxScore != Evaluator.NOT_RECOMMENDED) {
-                records.add(Pair.create(cr.getChannel(), maxScore));
+                records.add(new Pair<>(cr.getChannel(), maxScore));
             }
         }
         if (size > records.size()) {
diff --git a/src/com/android/tv/recommendation/RoutineWatchEvaluator.java b/src/com/android/tv/recommendation/RoutineWatchEvaluator.java
index b3952c0..9240682 100644
--- a/src/com/android/tv/recommendation/RoutineWatchEvaluator.java
+++ b/src/com/android/tv/recommendation/RoutineWatchEvaluator.java
@@ -19,9 +19,7 @@
 import android.support.annotation.Nullable;
 import android.support.annotation.VisibleForTesting;
 import android.text.TextUtils;
-
-import com.android.tv.data.api.Program;
-
+import com.android.tv.data.Program;
 import java.text.BreakIterator;
 import java.util.ArrayList;
 import java.util.Calendar;
diff --git a/src/com/android/tv/recommendation/WatchedProgram.java b/src/com/android/tv/recommendation/WatchedProgram.java
index 0da9c62..239de1f 100644
--- a/src/com/android/tv/recommendation/WatchedProgram.java
+++ b/src/com/android/tv/recommendation/WatchedProgram.java
@@ -16,7 +16,7 @@
 
 package com.android.tv.recommendation;
 
-import com.android.tv.data.api.Program;
+import com.android.tv.data.Program;
 
 public final class WatchedProgram {
     private final Program mProgram;
diff --git a/src/com/android/tv/search/DataManagerSearch.java b/src/com/android/tv/search/DataManagerSearch.java
index 1a0ada3..a649c0a 100644
--- a/src/com/android/tv/search/DataManagerSearch.java
+++ b/src/com/android/tv/search/DataManagerSearch.java
@@ -26,18 +26,15 @@
 import android.support.annotation.MainThread;
 import android.text.TextUtils;
 import android.util.Log;
-
 import com.android.tv.TvSingletons;
 import com.android.tv.data.ChannelDataManager;
+import com.android.tv.data.Program;
 import com.android.tv.data.ProgramDataManager;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
 import com.android.tv.search.LocalSearchProvider.SearchResult;
 import com.android.tv.util.MainThreadExecutor;
 import com.android.tv.util.Utils;
-
 import com.google.common.collect.ImmutableList;
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashSet;
diff --git a/src/com/android/tv/search/LocalSearchProvider.java b/src/com/android/tv/search/LocalSearchProvider.java
index 8699956..5652c98 100644
--- a/src/com/android/tv/search/LocalSearchProvider.java
+++ b/src/com/android/tv/search/LocalSearchProvider.java
@@ -17,6 +17,7 @@
 package com.android.tv.search;
 
 import android.app.SearchManager;
+import android.content.ContentProvider;
 import android.content.ContentValues;
 import android.database.Cursor;
 import android.database.MatrixCursor;
@@ -27,30 +28,21 @@
 import android.support.annotation.VisibleForTesting;
 import android.text.TextUtils;
 import android.util.Log;
-
+import com.android.tv.TvSingletons;
 import com.android.tv.common.CommonConstants;
 import com.android.tv.common.SoftPreconditions;
-import com.android.tv.common.dagger.init.SafePreDaggerInitializer;
 import com.android.tv.common.util.CommonUtils;
 import com.android.tv.common.util.PermissionUtils;
 import com.android.tv.perf.EventNames;
 import com.android.tv.perf.PerformanceMonitor;
 import com.android.tv.perf.TimerEvent;
 import com.android.tv.util.TvUriMatcher;
-
 import com.google.auto.value.AutoValue;
-
-import dagger.android.ContributesAndroidInjector;
-import dagger.android.DaggerContentProvider;
-
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
-import javax.inject.Inject;
-
-/** Content provider for local search */
-public class LocalSearchProvider extends DaggerContentProvider {
+public class LocalSearchProvider extends ContentProvider {
     private static final String TAG = "LocalSearchProvider";
     private static final boolean DEBUG = false;
 
@@ -87,18 +79,14 @@
     private static final String NO_LIVE_CONTENTS = "0";
     private static final String LIVE_CONTENTS = "1";
 
-    @Inject PerformanceMonitor mPerformanceMonitor;
+    private PerformanceMonitor mPerformanceMonitor;
 
     /** Used only for testing */
     private SearchInterface mSearchInterface;
 
     @Override
     public boolean onCreate() {
-        SafePreDaggerInitializer.init(getContext());
-        if (!super.onCreate()) {
-            Log.e(TAG, "LocalSearchProvider.onCreate() failed.");
-            return false;
-        }
+        mPerformanceMonitor = TvSingletons.getSingletons(getContext()).getPerformanceMonitor();
         return true;
     }
 
@@ -233,13 +221,6 @@
         throw new UnsupportedOperationException();
     }
 
-    /** Module for {@link LocalSearchProvider} */
-    @dagger.Module
-    public abstract static class Module {
-        @ContributesAndroidInjector
-        abstract LocalSearchProvider contributesLocalSearchProviderInjector();
-    }
-
     /** A placeholder to a search result. */
     @AutoValue
     public abstract static class SearchResult {
@@ -254,8 +235,6 @@
                     .setProgressPercentage(0);
         }
 
-        public abstract Builder toBuilder();
-
         @AutoValue.Builder
         abstract static class Builder {
             abstract Builder setChannelId(long value);
diff --git a/src/com/android/tv/search/ProgramGuideSearchFragment.java b/src/com/android/tv/search/ProgramGuideSearchFragment.java
index fa2e451..6c94bd3 100644
--- a/src/com/android/tv/search/ProgramGuideSearchFragment.java
+++ b/src/com/android/tv/search/ProgramGuideSearchFragment.java
@@ -21,18 +21,18 @@
 import android.graphics.drawable.BitmapDrawable;
 import android.os.AsyncTask;
 import android.os.Bundle;
-import androidx.leanback.app.SearchFragment;
-import androidx.leanback.widget.ArrayObjectAdapter;
-import androidx.leanback.widget.HeaderItem;
-import androidx.leanback.widget.ImageCardView;
-import androidx.leanback.widget.ListRow;
-import androidx.leanback.widget.ListRowPresenter;
-import androidx.leanback.widget.ObjectAdapter;
-import androidx.leanback.widget.OnItemViewClickedListener;
-import androidx.leanback.widget.Presenter;
-import androidx.leanback.widget.Row;
-import androidx.leanback.widget.RowPresenter;
-import androidx.leanback.widget.SearchBar;
+import android.support.v17.leanback.app.SearchFragment;
+import android.support.v17.leanback.widget.ArrayObjectAdapter;
+import android.support.v17.leanback.widget.HeaderItem;
+import android.support.v17.leanback.widget.ImageCardView;
+import android.support.v17.leanback.widget.ListRow;
+import android.support.v17.leanback.widget.ListRowPresenter;
+import android.support.v17.leanback.widget.ObjectAdapter;
+import android.support.v17.leanback.widget.OnItemViewClickedListener;
+import android.support.v17.leanback.widget.Presenter;
+import android.support.v17.leanback.widget.Row;
+import android.support.v17.leanback.widget.RowPresenter;
+import android.support.v17.leanback.widget.SearchBar;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.LayoutInflater;
diff --git a/src/com/android/tv/search/TvProviderSearch.java b/src/com/android/tv/search/TvProviderSearch.java
index c46938a..8a1f51f 100644
--- a/src/com/android/tv/search/TvProviderSearch.java
+++ b/src/com/android/tv/search/TvProviderSearch.java
@@ -308,7 +308,7 @@
             if (c != null && c.moveToNext() && !isRatingBlocked(c.getString(2))) {
                 String channelName = result.getTitle();
                 String channelNumber = result.getChannelNumber();
-                SearchResult.Builder builder = result.toBuilder();
+                SearchResult.Builder builder = SearchResult.builder();
                 long startUtcMillis = c.getLong(5);
                 long endUtcMillis = c.getLong(6);
                 builder.setTitle(c.getString(0));
diff --git a/src/com/android/tv/setup/SystemSetupActivity.java b/src/com/android/tv/setup/SystemSetupActivity.java
index 999b157..b2160b3 100644
--- a/src/com/android/tv/setup/SystemSetupActivity.java
+++ b/src/com/android/tv/setup/SystemSetupActivity.java
@@ -24,9 +24,9 @@
 import android.media.tv.TvInputInfo;
 import android.os.Bundle;
 import android.widget.Toast;
-
 import com.android.tv.R;
 import com.android.tv.SetupPassthroughActivity;
+import com.android.tv.TvSingletons;
 import com.android.tv.common.CommonConstants;
 import com.android.tv.common.ui.setup.SetupActivity;
 import com.android.tv.common.ui.setup.SetupMultiPaneFragment;
@@ -36,11 +36,6 @@
 import com.android.tv.util.SetupUtils;
 import com.android.tv.util.TvInputManagerHelper;
 
-import dagger.android.AndroidInjection;
-import dagger.android.ContributesAndroidInjector;
-
-import javax.inject.Inject;
-
 /** A activity to start input sources setup fragment for initial setup flow. */
 public class SystemSetupActivity extends SetupActivity {
     private static final String SYSTEM_SETUP =
@@ -48,17 +43,18 @@
     private static final int SHOW_RIPPLE_DURATION_MS = 266;
     private static final int REQUEST_CODE_START_SETUP_ACTIVITY = 1;
 
-    @Inject TvInputManagerHelper mInputManager;
+    private TvInputManagerHelper mInputManager;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
-        AndroidInjection.inject(this);
         super.onCreate(savedInstanceState);
         Intent intent = getIntent();
         if (!SYSTEM_SETUP.equals(intent.getAction())) {
             finish();
             return;
         }
+        TvSingletons singletons = TvSingletons.getSingletons(this);
+        mInputManager = singletons.getTvInputManagerHelper();
     }
 
     @Override
@@ -96,7 +92,7 @@
                             }
                             // Even though other app can handle the intent, the setup launched by
                             // Live
-                            // channels should go through TV app SetupPassthroughActivity.
+                            // channels should go through Live channels SetupPassthroughActivity.
                             intent.setComponent(
                                     new ComponentName(this, SetupPassthroughActivity.class));
                             try {
@@ -128,13 +124,4 @@
         }
         return false;
     }
-
-    /**
-     * Exports {@link SystemSetupActivity} for Dagger codegen to create the appropriate injector.
-     */
-    @dagger.Module
-    public abstract static class Module {
-        @ContributesAndroidInjector
-        abstract SystemSetupActivity contributeSystemSetupActivity();
-    }
 }
diff --git a/src/com/android/tv/ui/AppLayerTvView.java b/src/com/android/tv/ui/AppLayerTvView.java
index 4c54fb3..e2b64a1 100644
--- a/src/com/android/tv/ui/AppLayerTvView.java
+++ b/src/com/android/tv/ui/AppLayerTvView.java
@@ -21,6 +21,7 @@
 import android.view.SurfaceView;
 import android.view.View;
 import com.android.tv.common.compat.TvViewCompat;
+import com.android.tv.common.util.CommonUtils;
 import com.android.tv.common.util.Debug;
 
 /**
@@ -28,14 +29,9 @@
  *
  * <p>Once an app starts using additional window like SubPanel and it gets window focus, the {@link
  * android.media.tv.TvView#setMain()} does not work because its implementation assumes that the app
- * uses only application layer.
- *
- * <p>TODO: remove this class once the TvView.setMain() is revisited.
+ * uses only application layer. TODO: remove this class once the TvView.setMain() is revisited.
  */
 public class AppLayerTvView extends TvViewCompat {
-
-    boolean mUseSecureSurface = true;
-
     public AppLayerTvView(Context context) {
         super(context);
     }
@@ -48,11 +44,6 @@
         super(context, attrs, defStyleAttr);
     }
 
-    /** Set the security of children {@link SurfaceView}s to {@code secure} */
-    public void setUseSecureSurface(boolean secure) {
-        mUseSecureSurface = secure;
-    }
-
     @Override
     public boolean hasWindowFocus() {
         return true;
@@ -62,7 +53,7 @@
     public void onViewAdded(View child) {
         if (child instanceof SurfaceView) {
             // Note: See b/29118070 for detail.
-            ((SurfaceView) child).setSecure(mUseSecureSurface);
+            ((SurfaceView) child).setSecure(!CommonUtils.isDeveloper());
         }
         super.onViewAdded(child);
     }
diff --git a/src/com/android/tv/ui/ChannelBannerView.java b/src/com/android/tv/ui/ChannelBannerView.java
index f078121..00ac7e3 100644
--- a/src/com/android/tv/ui/ChannelBannerView.java
+++ b/src/com/android/tv/ui/ChannelBannerView.java
@@ -46,15 +46,13 @@
 import android.widget.ProgressBar;
 import android.widget.RelativeLayout;
 import android.widget.TextView;
-
 import com.android.tv.R;
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.common.feature.CommonFeatures;
 import com.android.tv.common.singletons.HasSingletons;
-import com.android.tv.data.ProgramImpl;
+import com.android.tv.data.Program;
 import com.android.tv.data.StreamInfo;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
 import com.android.tv.dvr.DvrManager;
 import com.android.tv.dvr.data.ScheduledRecording;
 import com.android.tv.parental.ContentRatingsManager;
@@ -66,9 +64,7 @@
 import com.android.tv.util.images.ImageLoader;
 import com.android.tv.util.images.ImageLoader.ImageLoaderCallback;
 import com.android.tv.util.images.ImageLoader.LoadTvInputLogoTask;
-
 import com.google.common.collect.ImmutableList;
-
 import javax.inject.Provider;
 
 /** A view to render channel banner. */
@@ -122,7 +118,6 @@
     private final TvInputManagerHelper mTvInputManagerHelper;
     // TvOverlayManager is always created after ChannelBannerView
     private final Provider<TvOverlayManager> mTvOverlayManager;
-    private final AccessibilityManager mAccessibilityManager;
 
     private View mChannelView;
 
@@ -270,12 +265,12 @@
         mContentRatingsManager = mTvInputManagerHelper.getContentRatingsManager();
 
         mNoProgram =
-                new ProgramImpl.Builder()
+                new Program.Builder()
                         .setTitle(context.getString(R.string.channel_banner_no_title))
                         .setDescription(EMPTY_STRING)
                         .build();
         mLockedChannelProgram =
-                new ProgramImpl.Builder()
+                new Program.Builder()
                         .setTitle(context.getString(R.string.channel_banner_locked_channel_title))
                         .setDescription(EMPTY_STRING)
                         .build();
@@ -283,7 +278,8 @@
             sClosedCaptionMark = context.getString(R.string.closed_caption);
         }
         mAutoHideScheduler = new AutoHideScheduler(context, this::hide);
-        mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
+        context.getSystemService(AccessibilityManager.class)
+                .addAccessibilityStateChangeListener(mAutoHideScheduler);
     }
 
     @Override
@@ -323,18 +319,6 @@
     }
 
     @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        mAccessibilityManager.addAccessibilityStateChangeListener(mAutoHideScheduler);
-    }
-
-    @Override
-    protected void onDetachedFromWindow() {
-        mAccessibilityManager.removeAccessibilityStateChangeListener(mAutoHideScheduler);
-        super.onDetachedFromWindow();
-    }
-
-    @Override
     public void onEnterAction(boolean fromEmptyScene) {
         resetAnimationEffects();
         if (fromEmptyScene) {
@@ -564,7 +548,7 @@
         return new ImageLoaderCallback<ChannelBannerView>(channelBannerView) {
             @Override
             public void onBitmapLoaded(ChannelBannerView view, @Nullable Bitmap logo) {
-                if (!channel.equals(view.mCurrentChannel)) {
+                if (channel.equals(view.mCurrentChannel)) {
                     // The logo is obsolete.
                     return;
                 }
@@ -751,23 +735,15 @@
         } else {
             ImmutableList<TvContentRating> ratings =
                     (program == null) ? null : program.getContentRatings();
-            int ratingsViewIndex = 0;
-            if (ratings != null) {
-                for (int i = 0; i < ratings.size(); i++) {
-                    if (ratingsViewIndex < DISPLAYED_CONTENT_RATINGS_COUNT
-                            && !TextUtils.isEmpty(
-                                    mContentRatingsManager.getDisplayNameForRating(
-                                            ratings.get(i)))) {
-                        mContentRatingsTextViews[ratingsViewIndex].setText(
-                                mContentRatingsManager.getDisplayNameForRating(ratings.get(i)));
-                        mContentRatingsTextViews[ratingsViewIndex].setVisibility(View.VISIBLE);
-                        ratingsViewIndex++;
-                    }
+            for (int i = 0; i < DISPLAYED_CONTENT_RATINGS_COUNT; i++) {
+                if (ratings == null || ratings.size() <= i) {
+                    mContentRatingsTextViews[i].setVisibility(View.GONE);
+                } else {
+                    mContentRatingsTextViews[i].setText(
+                            mContentRatingsManager.getDisplayNameForRating(ratings.get(i)));
+                    mContentRatingsTextViews[i].setVisibility(View.VISIBLE);
                 }
             }
-            while (ratingsViewIndex < DISPLAYED_CONTENT_RATINGS_COUNT) {
-                mContentRatingsTextViews[ratingsViewIndex++].setVisibility(View.GONE);
-            }
         }
     }
 
diff --git a/src/com/android/tv/ui/DetailsActivity.java b/src/com/android/tv/ui/DetailsActivity.java
index 92c13f5..80c0f64 100644
--- a/src/com/android/tv/ui/DetailsActivity.java
+++ b/src/com/android/tv/ui/DetailsActivity.java
@@ -16,11 +16,12 @@
 
 package com.android.tv.ui;
 
+import android.app.Activity;
 import android.content.pm.PackageManager;
 import android.os.Bundle;
 import android.os.Parcelable;
 import android.support.annotation.NonNull;
-import androidx.leanback.app.DetailsFragment;
+import android.support.v17.leanback.app.DetailsFragment;
 import android.transition.Transition;
 import android.transition.Transition.TransitionListener;
 import android.util.Log;
@@ -34,12 +35,9 @@
 import com.android.tv.dvr.ui.browse.RecordedProgramDetailsFragment;
 import com.android.tv.dvr.ui.browse.ScheduledRecordingDetailsFragment;
 import com.android.tv.dvr.ui.browse.SeriesRecordingDetailsFragment;
-import dagger.android.ContributesAndroidInjector;
-import dagger.android.DaggerActivity;
 
 /** Activity to show details view. */
-public class DetailsActivity extends DaggerActivity
-        implements PinDialogFragment.OnPinCheckedListener {
+public class DetailsActivity extends Activity implements PinDialogFragment.OnPinCheckedListener {
     private static final String TAG = "DetailsActivity";
 
     private static final long INVALID_RECORD_ID = -1;
@@ -208,15 +206,4 @@
         }
         finish();
     }
-
-    /** Exports {@link DaggerActivity} for Dagger codegen to create the appropriate injector. */
-    @dagger.Module
-    public abstract static class Module {
-        @ContributesAndroidInjector
-        abstract DetailsActivity contributesDetailsActivityInjector();
-
-        @ContributesAndroidInjector
-        abstract CurrentRecordingDetailsFragment
-                contributesCurrentRecordingDetailsFragmentInjector();
-    }
 }
diff --git a/src/com/android/tv/ui/GuidedActionsStylistWithDivider.java b/src/com/android/tv/ui/GuidedActionsStylistWithDivider.java
index 3aba5d1..9685b04 100644
--- a/src/com/android/tv/ui/GuidedActionsStylistWithDivider.java
+++ b/src/com/android/tv/ui/GuidedActionsStylistWithDivider.java
@@ -17,9 +17,9 @@
 package com.android.tv.ui;
 
 import android.content.Context;
-import androidx.leanback.app.GuidedStepFragment;
-import androidx.leanback.widget.GuidedAction;
-import androidx.leanback.widget.GuidedActionsStylist;
+import android.support.v17.leanback.app.GuidedStepFragment;
+import android.support.v17.leanback.widget.GuidedAction;
+import android.support.v17.leanback.widget.GuidedActionsStylist;
 import com.android.tv.R;
 
 /** Extended stylist class used for {@link GuidedStepFragment} with divider support. */
diff --git a/src/com/android/tv/ui/OnRepeatedKeyInterceptListener.java b/src/com/android/tv/ui/OnRepeatedKeyInterceptListener.java
index 703dc24..9b916af 100644
--- a/src/com/android/tv/ui/OnRepeatedKeyInterceptListener.java
+++ b/src/com/android/tv/ui/OnRepeatedKeyInterceptListener.java
@@ -17,7 +17,7 @@
 
 import android.os.Message;
 import android.support.annotation.NonNull;
-import androidx.leanback.widget.VerticalGridView;
+import android.support.v17.leanback.widget.VerticalGridView;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.View;
diff --git a/src/com/android/tv/ui/ProgramDetailsFragment.java b/src/com/android/tv/ui/ProgramDetailsFragment.java
index bfcebd7..88a7b2c 100644
--- a/src/com/android/tv/ui/ProgramDetailsFragment.java
+++ b/src/com/android/tv/ui/ProgramDetailsFragment.java
@@ -23,23 +23,21 @@
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.support.annotation.Nullable;
+import android.support.v17.leanback.app.DetailsFragment;
+import android.support.v17.leanback.widget.Action;
+import android.support.v17.leanback.widget.ArrayObjectAdapter;
+import android.support.v17.leanback.widget.ClassPresenterSelector;
+import android.support.v17.leanback.widget.DetailsOverviewRow;
+import android.support.v17.leanback.widget.DetailsOverviewRowPresenter;
+import android.support.v17.leanback.widget.OnActionClickedListener;
+import android.support.v17.leanback.widget.PresenterSelector;
+import android.support.v17.leanback.widget.SparseArrayObjectAdapter;
+import android.support.v17.leanback.widget.VerticalGridView;
 import android.text.TextUtils;
-
-import androidx.leanback.app.DetailsFragment;
-import androidx.leanback.widget.Action;
-import androidx.leanback.widget.ArrayObjectAdapter;
-import androidx.leanback.widget.ClassPresenterSelector;
-import androidx.leanback.widget.DetailsOverviewRow;
-import androidx.leanback.widget.DetailsOverviewRowPresenter;
-import androidx.leanback.widget.OnActionClickedListener;
-import androidx.leanback.widget.PresenterSelector;
-import androidx.leanback.widget.SparseArrayObjectAdapter;
-import androidx.leanback.widget.VerticalGridView;
-
 import com.android.tv.R;
 import com.android.tv.TvSingletons;
 import com.android.tv.common.feature.CommonFeatures;
-import com.android.tv.data.ProgramImpl;
+import com.android.tv.data.Program;
 import com.android.tv.data.api.Channel;
 import com.android.tv.dvr.DvrDataManager;
 import com.android.tv.dvr.DvrManager;
@@ -66,7 +64,7 @@
     protected DetailsViewBackgroundHelper mBackgroundHelper;
     private ArrayObjectAdapter mRowsAdapter;
     private DetailsOverviewRow mDetailsOverview;
-    private ProgramImpl mProgram;
+    private Program mProgram;
     private String mInputId;
     private ScheduledRecording mScheduledRecording;
     private DvrManager mDvrManager;
@@ -139,7 +137,7 @@
      *     the detail activity and fragment will be ended.
      */
     private boolean onLoadDetails(Bundle args) {
-        ProgramImpl program = args.getParcelable(DetailsActivity.PROGRAM);
+        Program program = args.getParcelable(DetailsActivity.PROGRAM);
         long channelId = args.getLong(DetailsActivity.CHANNEL_ID);
         String inputId = args.getString(DetailsActivity.INPUT_ID);
         if (program != null && channelId != Channel.INVALID_ID && !TextUtils.isEmpty(inputId)) {
diff --git a/src/com/android/tv/ui/SelectInputView.java b/src/com/android/tv/ui/SelectInputView.java
index a0cfad3..f4949f0 100644
--- a/src/com/android/tv/ui/SelectInputView.java
+++ b/src/com/android/tv/ui/SelectInputView.java
@@ -22,8 +22,8 @@
 import android.media.tv.TvInputManager;
 import android.media.tv.TvInputManager.TvInputCallback;
 import android.support.annotation.NonNull;
-import androidx.leanback.widget.VerticalGridView;
-import androidx.recyclerview.widget.RecyclerView;
+import android.support.v17.leanback.widget.VerticalGridView;
+import android.support.v7.widget.RecyclerView;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
diff --git a/src/com/android/tv/ui/TunableTvView.java b/src/com/android/tv/ui/TunableTvView.java
index a736e79..5ac6bd8 100644
--- a/src/com/android/tv/ui/TunableTvView.java
+++ b/src/com/android/tv/ui/TunableTvView.java
@@ -54,13 +54,11 @@
 import android.view.accessibility.AccessibilityManager;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
-
 import com.android.tv.InputSessionManager;
 import com.android.tv.InputSessionManager.TvViewSession;
 import com.android.tv.R;
 import com.android.tv.TvSingletons;
 import com.android.tv.analytics.Tracker;
-import com.android.tv.common.BuildConfig;
 import com.android.tv.common.CommonConstants;
 import com.android.tv.common.compat.TvInputConstantCompat;
 import com.android.tv.common.compat.TvViewCompat.TvInputCallbackCompat;
@@ -69,11 +67,11 @@
 import com.android.tv.common.util.Debug;
 import com.android.tv.common.util.DurationTimer;
 import com.android.tv.common.util.PermissionUtils;
+import com.android.tv.data.Program;
 import com.android.tv.data.ProgramDataManager;
 import com.android.tv.data.StreamInfo;
 import com.android.tv.data.WatchedHistoryManager;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
 import com.android.tv.features.TvFeatures;
 import com.android.tv.parental.ContentRatingsManager;
 import com.android.tv.parental.ParentalControlSettings;
@@ -83,9 +81,6 @@
 import com.android.tv.util.TvInputManagerHelper;
 import com.android.tv.util.Utils;
 import com.android.tv.util.images.ImageLoader;
-
-import com.android.tv.common.flags.LegacyFlags;
-
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.List;
@@ -290,12 +285,12 @@
                                         if (mVideoWidth <= 0 || mVideoHeight <= 0) {
                                             mVideoDisplayAspectRatio = 0.0f;
                                         } else {
-                                            float videoPixelAspectRatio =
+                                            float VideoPixelAspectRatio =
                                                     track.getVideoPixelAspectRatio();
-                                            mVideoDisplayAspectRatio = (float) mVideoWidth
-                                                    / mVideoHeight;
-                                            mVideoDisplayAspectRatio *= videoPixelAspectRatio > 0 ?
-                                                    videoPixelAspectRatio : 1;
+                                            mVideoDisplayAspectRatio =
+                                                    VideoPixelAspectRatio
+                                                            * mVideoWidth
+                                                            / mVideoHeight;
                                         }
                                     } else if (type == TvTrackInfo.TYPE_AUDIO) {
                                         mAudioChannelCount = track.getAudioChannelCount();
@@ -322,7 +317,7 @@
                     if (DEBUG) Log.d(TAG, "onVideoAvailable: {inputId=" + inputId + "}");
                     Debug.getTimer(Debug.TAG_START_UP_TIMER)
                             .log(
-                                    "Start up of TV app ends,"
+                                    "Start up of Live TV ends,"
                                             + " TunableTvView.onVideoAvailable resets timer");
                     Debug.getTimer(Debug.TAG_START_UP_TIMER).reset();
                     Debug.removeTimer(Debug.TAG_START_UP_TIMER);
@@ -478,12 +473,8 @@
     }
 
     public void initialize(
-            ProgramDataManager programDataManager,
-            TvInputManagerHelper tvInputManagerHelper,
-            LegacyFlags mLegacyFlags) {
+            ProgramDataManager programDataManager, TvInputManagerHelper tvInputManagerHelper) {
         mTvView = findViewById(R.id.tv_view);
-        mTvView.setUseSecureSurface(!BuildConfig.ENG && !mLegacyFlags.enableDeveloperFeatures());
-
         mProgramDataManager = programDataManager;
         mInputManagerHelper = tvInputManagerHelper;
         mContentRatingsManager = tvInputManagerHelper.getContentRatingsManager();
@@ -562,9 +553,7 @@
     }
 
     public void setMain() {
-        if (PermissionUtils.hasChangeHdmiCecActiveSource(getContext())) {
-            mTvView.setMain();
-        }
+        mTvView.setMain();
     }
 
     public void setWatchedHistoryManager(WatchedHistoryManager watchedHistoryManager) {
@@ -664,22 +653,17 @@
         // To reduce the IPCs, unregister the callback here and register it when necessary.
         mTvView.setTimeShiftPositionCallback(null);
         setTimeShiftAvailable(false);
+        if (needSurfaceSizeUpdate && mFixedSurfaceWidth > 0 && mFixedSurfaceHeight > 0) {
+            // When the input is changed, TvView recreates its SurfaceView internally.
+            // So we need to call SurfaceHolder.setFixedSize for the new SurfaceView.
+            getSurfaceView().getHolder().setFixedSize(mFixedSurfaceWidth, mFixedSurfaceHeight);
+        }
         mVideoUnavailableReason = TvInputManager.VIDEO_UNAVAILABLE_REASON_TUNING;
         if (mTvViewSession != null) {
             mTvViewSession.tune(channel, params, listener);
         } else {
             mTvView.tune(mInputInfo.getId(), mCurrentChannel.getUri(), params);
         }
-        if (needSurfaceSizeUpdate && mFixedSurfaceWidth > 0 && mFixedSurfaceHeight > 0) {
-            // When the input is changed, TvView recreates its SurfaceView internally.
-            // So we need to call SurfaceHolder.setFixedSize for the new SurfaceView.
-            SurfaceView surfaceView = getSurfaceView();
-            if (surfaceView != null) {
-                surfaceView.getHolder().setFixedSize(mFixedSurfaceWidth, mFixedSurfaceHeight);
-            } else {
-                Log.w(TAG, "Failed to set fixed size for surface view: Null surface view");
-            }
-        }
         updateBlockScreenAndMuting();
         if (mOnTuneListener != null) {
             mOnTuneListener.onStreamInfoChanged(this, true);
diff --git a/src/com/android/tv/ui/TvOverlayManager.java b/src/com/android/tv/ui/TvOverlayManager.java
index 0ab7c68..b2854a1 100644
--- a/src/com/android/tv/ui/TvOverlayManager.java
+++ b/src/com/android/tv/ui/TvOverlayManager.java
@@ -33,7 +33,6 @@
 import android.view.KeyEvent;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener;
-
 import com.android.tv.ChannelTuner;
 import com.android.tv.MainActivity;
 import com.android.tv.MainActivity.KeyHandlerResultType;
@@ -48,7 +47,6 @@
 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.data.ProgramDataManager;
 import com.android.tv.dialog.DvrHistoryDialogFragment;
 import com.android.tv.dialog.FullscreenDialogFragment;
 import com.android.tv.dialog.HalfSizedDialogFragment;
@@ -70,12 +68,6 @@
 import com.android.tv.ui.sidepanel.SideFragmentManager;
 import com.android.tv.ui.sidepanel.parentalcontrols.RatingsFragment;
 import com.android.tv.util.TvInputManagerHelper;
-
-import com.google.auto.factory.AutoFactory;
-import com.google.auto.factory.Provided;
-
-import com.android.tv.common.flags.LegacyFlags;
-
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
@@ -87,7 +79,6 @@
 
 /** A class responsible for the life cycle and event handling of the pop-ups over TV view. */
 @UiThread
-@AutoFactory
 public class TvOverlayManager implements AccessibilityStateChangeListener {
     private static final String TAG = "TvOverlayManager";
     private static final boolean DEBUG = false;
@@ -225,7 +216,6 @@
 
     private final List<Runnable> mPendingActions = new ArrayList<>();
     private final Queue<PendingDialogAction> mPendingDialogActionQueue = new LinkedList<>();
-    private final LegacyFlags mLegacyFlags;
 
     private OnBackStackChangedListener mOnBackStackChangedListener;
 
@@ -239,17 +229,12 @@
             InputBannerView inputBannerView,
             SelectInputView selectInputView,
             ViewGroup sceneContainer,
-            ProgramGuideSearchFragment searchFragment,
-            @Provided LegacyFlags legacyFlags,
-            @Provided ChannelDataManager channelDataManager,
-            @Provided TvInputManagerHelper tvInputManager,
-            @Provided ProgramDataManager programDataManager) {
+            ProgramGuideSearchFragment searchFragment) {
         mMainActivity = mainActivity;
         mChannelTuner = channelTuner;
         TvSingletons singletons = TvSingletons.getSingletons(mainActivity);
-        mLegacyFlags = legacyFlags;
-        mChannelDataManager = channelDataManager;
-        mInputManager = tvInputManager;
+        mChannelDataManager = singletons.getChannelDataManager();
+        mInputManager = singletons.getTvInputManagerHelper();
         mTvView = tvView;
         mChannelBannerView = channelBannerView;
         mKeypadChannelSwitchView = keypadChannelSwitchView;
@@ -286,7 +271,7 @@
                         tvView,
                         optionsManager,
                         menuView,
-                        new MenuRowFactory(mainActivity, tvView, this.mLegacyFlags),
+                        new MenuRowFactory(mainActivity, tvView),
                         new Menu.OnMenuVisibilityChangeListener() {
                             @Override
                             public void onMenuVisibilityChange(boolean visible) {
@@ -319,9 +304,9 @@
                 new ProgramGuide(
                         mainActivity,
                         channelTuner,
-                        mInputManager,
+                        singletons.getTvInputManagerHelper(),
                         mChannelDataManager,
-                        programDataManager,
+                        singletons.getProgramDataManager(),
                         dvrDataManager,
                         singletons.getDvrScheduleManager(),
                         singletons.getTracker(),
diff --git a/src/com/android/tv/ui/ViewUtils.java b/src/com/android/tv/ui/ViewUtils.java
index 431b311..f64a70b 100644
--- a/src/com/android/tv/ui/ViewUtils.java
+++ b/src/com/android/tv/ui/ViewUtils.java
@@ -18,11 +18,9 @@
 
 import android.animation.Animator;
 import android.animation.ValueAnimator;
-import android.os.Build;
 import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup.LayoutParams;
-
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 
@@ -35,9 +33,6 @@
     }
 
     public static void setTransitionAlpha(View v, float alpha) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
-            v.setTransitionAlpha(alpha);
-        }
         Method method;
         try {
             method = View.class.getDeclaredMethod("setTransitionAlpha", Float.TYPE);
diff --git a/src/com/android/tv/ui/sidepanel/ChannelCheckItem.java b/src/com/android/tv/ui/sidepanel/ChannelCheckItem.java
index de3ae75..2726839 100644
--- a/src/com/android/tv/ui/sidepanel/ChannelCheckItem.java
+++ b/src/com/android/tv/ui/sidepanel/ChannelCheckItem.java
@@ -19,14 +19,13 @@
 import android.text.TextUtils;
 import android.view.View;
 import android.widget.TextView;
-
 import com.android.tv.R;
 import com.android.tv.data.ChannelDataManager;
 import com.android.tv.data.ChannelDataManager.ChannelListener;
 import com.android.tv.data.OnCurrentProgramUpdatedListener;
+import com.android.tv.data.Program;
 import com.android.tv.data.ProgramDataManager;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
 
 public abstract class ChannelCheckItem extends CompoundButtonItem {
     private final ChannelDataManager mChannelDataManager;
diff --git a/src/com/android/tv/ui/sidepanel/CustomizeChannelListFragment.java b/src/com/android/tv/ui/sidepanel/CustomizeChannelListFragment.java
index b62a57e..62130b6 100644
--- a/src/com/android/tv/ui/sidepanel/CustomizeChannelListFragment.java
+++ b/src/com/android/tv/ui/sidepanel/CustomizeChannelListFragment.java
@@ -20,7 +20,7 @@
 import android.content.SharedPreferences;
 import android.media.tv.TvContract.Channels;
 import android.os.Bundle;
-import androidx.leanback.widget.VerticalGridView;
+import android.support.v17.leanback.widget.VerticalGridView;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.View;
diff --git a/src/com/android/tv/ui/sidepanel/DeveloperOptionFragment.java b/src/com/android/tv/ui/sidepanel/DeveloperOptionFragment.java
index e43568c..36ee5a2 100644
--- a/src/com/android/tv/ui/sidepanel/DeveloperOptionFragment.java
+++ b/src/com/android/tv/ui/sidepanel/DeveloperOptionFragment.java
@@ -16,38 +16,29 @@
 
 package com.android.tv.ui.sidepanel;
 
+import android.accounts.Account;
 import android.app.Activity;
-
-import com.android.tv.MainActivity;
+import android.support.annotation.NonNull;
+import android.util.Log;
+import android.widget.Toast;
 import com.android.tv.R;
-import com.android.tv.common.BuildConfig;
+import com.android.tv.TvSingletons;
 import com.android.tv.common.CommonPreferences;
 import com.android.tv.common.feature.CommonFeatures;
-import com.android.tv.perf.PerformanceMonitor;
+import com.android.tv.common.util.CommonUtils;
 
-import com.google.common.base.Optional;
-import com.google.common.collect.ImmutableList;
 
-import dagger.android.AndroidInjection;
 
-import com.android.tv.common.flags.LegacyFlags;
 
-import javax.inject.Inject;
+
+import java.util.ArrayList;
+import java.util.List;
 
 /** Options for developers only */
 public class DeveloperOptionFragment extends SideFragment {
+    private static final String TAG = "DeveloperOptionFragment";
     private static final String TRACKER_LABEL = "debug options";
 
-    @Inject Optional<AdditionalDeveloperItemsFactory> mAdditionalDeveloperItemsFactory;
-    @Inject PerformanceMonitor mPerformanceMonitor;
-    @Inject LegacyFlags mLegacyFlags;
-
-    @Override
-    public void onAttach(Activity activity) {
-        AndroidInjection.inject(this);
-        super.onAttach(activity);
-    }
-
     @Override
     protected String getTitle() {
         return getString(R.string.menu_developer_options);
@@ -59,15 +50,8 @@
     }
 
     @Override
-    protected ImmutableList<Item> getItemList() {
-        ImmutableList.Builder<Item> items = ImmutableList.builder();
-        if (mAdditionalDeveloperItemsFactory.isPresent()) {
-            items.addAll(
-                    mAdditionalDeveloperItemsFactory
-                            .get()
-                            .getAdditionalDevItems(getMainActivity()));
-            items.add(new DividerItem());
-        }
+    protected List<Item> getItemList() {
+        List<Item> items = new ArrayList<>();
         if (CommonFeatures.DVR.isEnabled(getContext())) {
             items.add(
                     new ActionItem(getString(R.string.dev_item_dvr_history)) {
@@ -77,7 +61,7 @@
                         }
                     });
         }
-        if (BuildConfig.ENG || mLegacyFlags.enableDeveloperFeatures()) {
+        if (CommonUtils.isDeveloper()) {
             items.add(
                     new ActionItem(getString(R.string.dev_item_watch_history)) {
                         @Override
@@ -103,21 +87,17 @@
                         CommonPreferences.setStoreTsStream(getContext(), isChecked());
                     }
                 });
-        if (BuildConfig.ENG || mLegacyFlags.enableDeveloperFeatures()) {
+        if (CommonUtils.isDeveloper()) {
             items.add(
                     new ActionItem(getString(R.string.dev_item_show_performance_monitor_log)) {
                         @Override
                         protected void onSelected() {
-                            mPerformanceMonitor.startPerformanceMonitorEventDebugActivity(
-                                    getContext());
+                            TvSingletons.getSingletons(getContext())
+                                    .getPerformanceMonitor()
+                                    .startPerformanceMonitorEventDebugActivity(getContext());
                         }
                     });
         }
-        return items.build();
-    }
-
-    /** Factory to create additional items. */
-    public interface AdditionalDeveloperItemsFactory {
-        ImmutableList<Item> getAdditionalDevItems(MainActivity mainActivity);
+        return items;
     }
 }
diff --git a/src/com/android/tv/ui/sidepanel/SettingsFragment.java b/src/com/android/tv/ui/sidepanel/SettingsFragment.java
index 1c03b6a..aa71fb7 100644
--- a/src/com/android/tv/ui/sidepanel/SettingsFragment.java
+++ b/src/com/android/tv/ui/sidepanel/SettingsFragment.java
@@ -35,7 +35,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
-/** Shows TV app settings. */
+/** Shows Live TV settings. */
 public class SettingsFragment extends SideFragment {
     private static final String TRACKER_LABEL = "settings";
 
diff --git a/src/com/android/tv/ui/sidepanel/SideFragment.java b/src/com/android/tv/ui/sidepanel/SideFragment.java
index 703b1e4..590f130 100644
--- a/src/com/android/tv/ui/sidepanel/SideFragment.java
+++ b/src/com/android/tv/ui/sidepanel/SideFragment.java
@@ -20,27 +20,24 @@
 import android.content.Context;
 import android.graphics.drawable.RippleDrawable;
 import android.os.Bundle;
-import androidx.recyclerview.widget.RecyclerView;
+import android.support.v17.leanback.widget.VerticalGridView;
+import android.support.v7.widget.RecyclerView;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
 import android.widget.TextView;
-
-import androidx.leanback.widget.VerticalGridView;
-
 import com.android.tv.MainActivity;
 import com.android.tv.R;
 import com.android.tv.TvSingletons;
 import com.android.tv.analytics.HasTrackerLabel;
 import com.android.tv.analytics.Tracker;
-import com.android.tv.common.dev.DeveloperPreferences;
 import com.android.tv.common.util.DurationTimer;
+import com.android.tv.common.util.SystemProperties;
 import com.android.tv.data.ChannelDataManager;
 import com.android.tv.data.ProgramDataManager;
 import com.android.tv.util.ViewCache;
-
 import java.util.List;
 
 public abstract class SideFragment<T extends Item> extends Fragment implements HasTrackerLabel {
@@ -59,7 +56,7 @@
             new RecyclerView.RecycledViewPool();
 
     private VerticalGridView mListView;
-    private ItemAdapter<T> mAdapter;
+    private ItemAdapter mAdapter;
     private SideFragmentListener mListener;
     private ChannelDataManager mChannelDataManager;
     private ProgramDataManager mProgramDataManager;
@@ -68,7 +65,6 @@
 
     private final int mHideKey;
     private final int mDebugHideKey;
-    private Context mContext;
 
     public SideFragment() {
         this(KeyEvent.KEYCODE_UNKNOWN, KeyEvent.KEYCODE_UNKNOWN);
@@ -77,7 +73,7 @@
     /**
      * @param hideKey the KeyCode used to hide the fragment
      * @param debugHideKey the KeyCode used to hide the fragment if {@link
-     *     DeveloperPreferences#USE_DEBUG_KEYS}.
+     *     SystemProperties#USE_DEBUG_KEYS}.
      */
     public SideFragment(int hideKey, int debugHideKey) {
         mHideKey = hideKey;
@@ -87,7 +83,6 @@
     @Override
     public void onAttach(Context context) {
         super.onAttach(context);
-        mContext = context;
         mChannelDataManager = getMainActivity().getChannelDataManager();
         mProgramDataManager = getMainActivity().getProgramDataManager();
         mTracker = TvSingletons.getSingletons(context).getTracker();
@@ -134,8 +129,7 @@
     }
 
     public final boolean isHideKeyForThisPanel(int keyCode) {
-        boolean debugKeysEnabled =
-                DeveloperPreferences.USE_DEBUG_KEYS.getDefaultIfContextNull(mContext);
+        boolean debugKeysEnabled = SystemProperties.USE_DEBUG_KEYS.getValue();
         return mHideKey != KeyEvent.KEYCODE_UNKNOWN
                 && (mHideKey == keyCode || (debugKeysEnabled && mDebugHideKey == keyCode));
     }
diff --git a/src/com/android/tv/ui/sidepanel/parentalcontrols/ChannelsBlockedFragment.java b/src/com/android/tv/ui/sidepanel/parentalcontrols/ChannelsBlockedFragment.java
index 620b701..b14bf78 100644
--- a/src/com/android/tv/ui/sidepanel/parentalcontrols/ChannelsBlockedFragment.java
+++ b/src/com/android/tv/ui/sidepanel/parentalcontrols/ChannelsBlockedFragment.java
@@ -23,7 +23,7 @@
 import android.os.Build.VERSION_CODES;
 import android.os.Bundle;
 import android.os.Handler;
-import androidx.leanback.widget.VerticalGridView;
+import android.support.v17.leanback.widget.VerticalGridView;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.View;
diff --git a/src/com/android/tv/ui/sidepanel/parentalcontrols/RatingsFragment.java b/src/com/android/tv/ui/sidepanel/parentalcontrols/RatingsFragment.java
index 60f8425..d1ae442 100644
--- a/src/com/android/tv/ui/sidepanel/parentalcontrols/RatingsFragment.java
+++ b/src/com/android/tv/ui/sidepanel/parentalcontrols/RatingsFragment.java
@@ -16,7 +16,6 @@
 
 package com.android.tv.ui.sidepanel.parentalcontrols;
 
-import android.app.Activity;
 import android.graphics.drawable.Drawable;
 import android.media.tv.TvContentRating;
 import android.os.Bundle;
@@ -25,9 +24,9 @@
 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.common.experiments.Experiments;
 import com.android.tv.dialog.WebDialogFragment;
 import com.android.tv.license.LicenseUtils;
 import com.android.tv.parental.ContentRatingSystem;
@@ -40,28 +39,18 @@
 import com.android.tv.ui.sidepanel.SideFragment;
 import com.android.tv.util.TvSettings;
 import com.android.tv.util.TvSettings.ContentRatingLevel;
-
 import com.google.common.collect.ImmutableList;
-
-import dagger.android.AndroidInjection;
-
-import com.android.tv.common.flags.LegacyFlags;
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
-import javax.inject.Inject;
-
 public class RatingsFragment extends SideFragment {
     private static final SparseIntArray sLevelResourceIdMap;
     private static final SparseIntArray sDescriptionResourceIdMap;
     private static final String TRACKER_LABEL = "Ratings";
     private int mItemsSize;
 
-    @Inject LegacyFlags mLegacyFlags;
-
     static {
         sLevelResourceIdMap = new SparseIntArray(5);
         sLevelResourceIdMap.put(TvSettings.CONTENT_RATING_LEVEL_NONE, R.string.option_rating_none);
@@ -112,7 +101,8 @@
     protected List<Item> getItemList() {
         List<Item> items = new ArrayList<>();
 
-        if (mBlockUnratedItem != null && mLegacyFlags.enableUnratedContentSettings()) {
+        if (mBlockUnratedItem != null
+                && Boolean.TRUE.equals(Experiments.ENABLE_UNRATED_CONTENT_SETTINGS.get())) {
             items.add(mBlockUnratedItem);
             items.add(new DividerItem());
         }
@@ -168,13 +158,7 @@
         super.onCreate(savedInstanceState);
         mParentalControlSettings = getMainActivity().getParentalControlSettings();
         mParentalControlSettings.loadRatings();
-    }
-
-    @Override
-    public void onAttach(Activity activity) {
-        AndroidInjection.inject(this);
-        super.onAttach(activity);
-        if (mLegacyFlags.enableUnratedContentSettings()) {
+        if (Boolean.TRUE.equals(Experiments.ENABLE_UNRATED_CONTENT_SETTINGS.get())) {
             mBlockUnratedItem =
                     new CheckBoxItem(
                             getResources().getString(R.string.option_block_unrated_programs)) {
@@ -195,8 +179,6 @@
                             }
                         }
                     };
-        } else {
-            mBlockUnratedItem = null;
         }
     }
 
@@ -253,7 +235,8 @@
             super.onSelected();
             mParentalControlSettings.setContentRatingLevel(
                     getMainActivity().getContentRatingsManager(), mRatingLevel);
-            if (mBlockUnratedItem != null && mLegacyFlags.enableUnratedContentSettings()) {
+            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(
diff --git a/src/com/android/tv/util/AsyncDbTask.java b/src/com/android/tv/util/AsyncDbTask.java
index 2e9a1ea..b352395 100644
--- a/src/com/android/tv/util/AsyncDbTask.java
+++ b/src/com/android/tv/util/AsyncDbTask.java
@@ -28,23 +28,18 @@
 import android.support.annotation.WorkerThread;
 import android.util.Log;
 import android.util.Range;
-
 import com.android.tv.TvSingletons;
 import com.android.tv.common.BuildConfig;
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.data.ChannelImpl;
-import com.android.tv.data.ProgramImpl;
+import com.android.tv.data.Program;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
 import com.android.tv.dvr.data.RecordedProgram;
-
 import com.google.common.base.Predicate;
-
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.Executor;
-
 import javax.inject.Qualifier;
 
 /**
@@ -128,7 +123,7 @@
                 return null;
             }
             if (Utils.isProgramsUri(mUri)
-                    && TvProviderUtils.checkSeriesIdColumn(context, Programs.CONTENT_URI)) {
+                            && TvProviderUtils.checkSeriesIdColumn(context, Programs.CONTENT_URI)) {
                 mProjection =
                         TvProviderUtils.addExtraColumnsToProjection(
                                 mProjection, TvProviderUtils.EXTRA_PROGRAM_COLUMN_SERIES_ID);
@@ -328,19 +323,10 @@
         }
     }
 
-    /**
-     * Gets an {@link List} of {@link ProgramImpl}s from {@link TvContract.Programs#CONTENT_URI}.
-     */
+    /** Gets an {@link List} of {@link Program}s from {@link TvContract.Programs#CONTENT_URI}. */
     public abstract static class AsyncProgramQueryTask extends AsyncQueryListTask<Program> {
         public AsyncProgramQueryTask(Executor executor, Context context) {
-            super(
-                    executor,
-                    context,
-                    Programs.CONTENT_URI,
-                    ProgramImpl.PROJECTION,
-                    null,
-                    null,
-                    null);
+            super(executor, context, Programs.CONTENT_URI, Program.PROJECTION, null, null, null);
         }
 
         public AsyncProgramQueryTask(
@@ -355,7 +341,7 @@
                     executor,
                     context,
                     uri,
-                    ProgramImpl.PROJECTION,
+                    Program.PROJECTION,
                     selection,
                     selectionArgs,
                     sortOrder,
@@ -364,7 +350,7 @@
 
         @Override
         protected final Program fromCursor(Cursor c) {
-            return ProgramImpl.fromCursor(c);
+            return Program.fromCursor(c);
         }
     }
 
@@ -390,7 +376,7 @@
     }
 
     /**
-     * Gets an {@link List} of {@link ProgramImpl}s for a given channel and period {@link
+     * Gets an {@link List} of {@link Program}s for a given channel and period {@link
      * TvContract#buildProgramsUriForChannel(long, long, long)}. If the {@code period} is {@code
      * null}, then all the programs is queried.
      */
@@ -424,7 +410,7 @@
         }
     }
 
-    /** Gets a single {@link ProgramImpl} from {@link TvContract.Programs#CONTENT_URI}. */
+    /** Gets a single {@link Program} from {@link TvContract.Programs#CONTENT_URI}. */
     public static class AsyncQueryProgramTask extends AsyncQueryItemTask<Program> {
 
         public AsyncQueryProgramTask(Executor executor, Context context, long programId) {
@@ -432,7 +418,7 @@
                     executor,
                     context,
                     TvContract.buildProgramUri(programId),
-                    ProgramImpl.PROJECTION,
+                    Program.PROJECTION,
                     null,
                     null,
                     null);
@@ -440,7 +426,7 @@
 
         @Override
         protected Program fromCursor(Cursor c) {
-            return ProgramImpl.fromCursor(c);
+            return Program.fromCursor(c);
         }
     }
 
diff --git a/src/com/android/tv/util/OnboardingUtils.java b/src/com/android/tv/util/OnboardingUtils.java
index 4fae2f0..3b72e09 100644
--- a/src/com/android/tv/util/OnboardingUtils.java
+++ b/src/com/android/tv/util/OnboardingUtils.java
@@ -27,9 +27,7 @@
     private static final String PREF_KEY_ONBOARDING_VERSION_CODE = "pref_onbaording_versionCode";
     private static final int ONBOARDING_VERSION = 1;
 
-    // Replace as needed
-    private static final String MERCHANT_COLLECTION_URL_STRING =
-            "https://play.google.com/store/apps/collection/promotion_3001bf9_ATV_livechannels";
+    private static final String MERCHANT_COLLECTION_URL_STRING = getMerchantCollectionUrl();
 
     /** Intent to show merchant collection in online store. */
     public static final Intent ONLINE_STORE_INTENT =
@@ -71,5 +69,10 @@
                 .apply();
     }
 
+    /** 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/SetupUtils.java b/src/com/android/tv/util/SetupUtils.java
index 52b3e3e..a9b67fa 100644
--- a/src/com/android/tv/util/SetupUtils.java
+++ b/src/com/android/tv/util/SetupUtils.java
@@ -307,7 +307,8 @@
     }
 
     /**
-     * Called when TV app is launched. Once it is called, {@link #isFirstTune} will return false.
+     * Called when Live channels app is launched. Once it is called, {@link #isFirstTune} will
+     * return false.
      */
     public void onTuned() {
         if (!mIsFirstTune) {
diff --git a/common/src/com/android/tv/common/util/sql/SqlParams.java b/src/com/android/tv/util/SqlParams.java
similarity index 97%
rename from common/src/com/android/tv/common/util/sql/SqlParams.java
rename to src/com/android/tv/util/SqlParams.java
index 87fcabd..fa557ba 100644
--- a/common/src/com/android/tv/common/util/sql/SqlParams.java
+++ b/src/com/android/tv/util/SqlParams.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package com.android.tv.common.util.sql;
+package com.android.tv.util;
 
 import android.database.DatabaseUtils;
 import android.support.annotation.Nullable;
diff --git a/src/com/android/tv/util/TvInputManagerHelper.java b/src/com/android/tv/util/TvInputManagerHelper.java
index 23c9b49..cb7d985 100644
--- a/src/com/android/tv/util/TvInputManagerHelper.java
+++ b/src/com/android/tv/util/TvInputManagerHelper.java
@@ -46,8 +46,6 @@
 import com.android.tv.parental.ParentalControlSettings;
 import com.android.tv.util.images.ImageCache;
 import com.android.tv.util.images.ImageLoader;
-import com.google.common.collect.Ordering;
-import com.android.tv.common.flags.LegacyFlags;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -129,7 +127,6 @@
     private static final String PERMISSION_ACCESS_ALL_EPG_DATA =
             "com.android.providers.tv.permission.ACCESS_ALL_EPG_DATA";
     private static final String[] mPhysicalTunerBlackList = {
-        "com.google.android.videos", // Play Movies
     };
     private static final String META_LABEL_SORT_KEY = "input_sort_key";
 
@@ -161,10 +158,6 @@
     }
 
     private static final String[] PARTNER_TUNER_INPUT_PREFIX_BLACKLIST = {
-        /* Begin_AOSP_Comment_Out
-        // Disabled partner's tuner input prefix list.
-        "com.mediatek.tvinput/.dtv"
-        End_AOSP_Comment_Out */
     };
 
     private static final String[] TESTABLE_INPUTS = {
@@ -299,8 +292,8 @@
     private boolean mAllow3rdPartyInputs;
 
     @Inject
-    public TvInputManagerHelper(@ApplicationContext Context context, LegacyFlags legacyFlags) {
-        this(context, createTvInputManagerWrapper(context), legacyFlags);
+    public TvInputManagerHelper(@ApplicationContext Context context) {
+        this(context, createTvInputManagerWrapper(context));
     }
 
     @Nullable
@@ -312,14 +305,12 @@
 
     @VisibleForTesting
     protected TvInputManagerHelper(
-            Context context,
-            @Nullable TvInputManagerInterface tvInputManager,
-            LegacyFlags legacyFlags) {
+            Context context, @Nullable TvInputManagerInterface tvInputManager) {
         mContext = context.getApplicationContext();
         mPackageManager = context.getPackageManager();
         mTvInputManager = tvInputManager;
         mContentRatingsManager = new ContentRatingsManager(context, tvInputManager);
-        mParentalControlSettings = new ParentalControlSettings(context, legacyFlags);
+        mParentalControlSettings = new ParentalControlSettings(context);
         mTvInputInfoComparator = new InputComparatorInternal(this);
         mContentObserver =
                 new ContentObserver(mHandler) {
@@ -357,6 +348,7 @@
         updateAllow3rdPartyInputs();
         mTvInputManager.registerCallback(mInternalCallback, mHandler);
         initInputMaps();
+        mContentRatingsManager.update();
     }
 
     public void stop() {
@@ -454,12 +446,10 @@
     }
 
     /** Loads label of {@code info}. */
-    @Nullable
     public String loadLabel(TvInputInfo info) {
         String label = mTvInputLabels.get(info.getId());
         if (label == null) {
-            CharSequence labelSequence = info.loadLabel(mContext);
-            label = labelSequence == null ? null : labelSequence.toString();
+            label = info.loadLabel(mContext).toString();
             mTvInputLabels.put(info.getId(), label);
         }
         return label;
@@ -713,8 +703,6 @@
     @VisibleForTesting
     static class InputComparatorInternal implements Comparator<TvInputInfo> {
         private final TvInputManagerHelper mInputManager;
-        private static final Ordering<Comparable> NULL_FIRST_STRING_ORDERING =
-                Ordering.natural().nullsFirst();
 
         public InputComparatorInternal(TvInputManagerHelper inputManager) {
             mInputManager = inputManager;
@@ -725,8 +713,7 @@
             if (mInputManager.isPartnerInput(lhs) != mInputManager.isPartnerInput(rhs)) {
                 return mInputManager.isPartnerInput(lhs) ? -1 : 1;
             }
-            return NULL_FIRST_STRING_ORDERING.compare(
-                    mInputManager.loadLabel(lhs), mInputManager.loadLabel(rhs));
+            return mInputManager.loadLabel(lhs).compareTo(mInputManager.loadLabel(rhs));
         }
     }
 
@@ -808,7 +795,7 @@
             if (TextUtils.isEmpty(label)) {
                 label = mTvInputManagerHelper.loadLabel(input);
             }
-            return label == null ? "" : label;
+            return label;
         }
 
         private int getPriority(TvInputInfo info) {
diff --git a/src/com/android/tv/util/TvProviderUtils.java b/src/com/android/tv/util/TvProviderUtils.java
index d931dcd..6b5aaec 100644
--- a/src/com/android/tv/util/TvProviderUtils.java
+++ b/src/com/android/tv/util/TvProviderUtils.java
@@ -27,7 +27,7 @@
 import android.support.annotation.VisibleForTesting;
 import android.support.annotation.WorkerThread;
 import android.util.Log;
-import com.android.tv.data.api.BaseProgram;
+import com.android.tv.data.BaseProgram;
 import com.android.tv.features.PartnerFeatures;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -67,9 +67,6 @@
     @WorkerThread
     public static synchronized boolean checkSeriesIdColumn(Context context, Uri uri) {
         boolean canCreateColumn = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O);
-        canCreateColumn =
-                (canCreateColumn
-                        || PartnerFeatures.TVPROVIDER_ALLOWS_COLUMN_CREATION.isEnabled(context));
         if (!canCreateColumn) {
             return false;
         }
@@ -115,9 +112,6 @@
     @WorkerThread
     public static synchronized boolean checkStateColumn(Context context, Uri uri) {
         boolean canCreateColumn = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O);
-        canCreateColumn =
-                (canCreateColumn
-                        || PartnerFeatures.TVPROVIDER_ALLOWS_COLUMN_CREATION.isEnabled(context));
         if (!canCreateColumn) {
             return false;
         }
@@ -150,8 +144,8 @@
         return TRUE.equals(sRecordedProgramHasStateColumn);
     }
 
-    public static String[] addExtraColumnsToProjection(
-            String[] projection, @TvProviderExtraColumn String column) {
+    public static String[] addExtraColumnsToProjection(String[] projection,
+            @TvProviderExtraColumn String column) {
         List<String> projectionList = new ArrayList<>(Arrays.asList(projection));
         if (!projectionList.contains(column)) {
             projectionList.add(column);
diff --git a/src/com/android/tv/util/TvTrackInfoUtils.java b/src/com/android/tv/util/TvTrackInfoUtils.java
index ae30df1..4ec96c6 100644
--- a/src/com/android/tv/util/TvTrackInfoUtils.java
+++ b/src/com/android/tv/util/TvTrackInfoUtils.java
@@ -17,16 +17,9 @@
 
 import android.content.Context;
 import android.media.tv.TvTrackInfo;
-import android.os.Build;
-import android.os.LocaleList;
 import android.text.TextUtils;
 import android.util.Log;
-
 import com.android.tv.R;
-
-import com.google.common.collect.Iterables;
-
-import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.HashSet;
 import java.util.List;
@@ -45,19 +38,17 @@
     private static final int AUDIO_CHANNEL_SURROUND_8 = 8;
 
     /**
-     * Compares how closely two {@link android.media.tv.TvTrackInfo}s match {@code languages},
-     * {@code channelCount} and {@code id} in that precedence. A listed sorted with this comparator
-     * has the worst matches first.
+     * Compares how closely two {@link android.media.tv.TvTrackInfo}s match {@code language}, {@code
+     * channelCount} and {@code id} in that precedence.
      *
      * @param id The track id to match.
-     * @param languages The prioritized list of languages. Languages earlier in the list are a
-     *     better match.
+     * @param language The language to match.
      * @param channelCount The channel count to match.
      * @return -1 if lhs is a worse match, 0 if lhs and rhs match equally and 1 if lhs is a better
      *     match.
      */
     public static Comparator<TvTrackInfo> createComparator(
-            final String id, final List<String> languages, final int channelCount) {
+            final String id, final String language, final int channelCount) {
         return (TvTrackInfo lhs, TvTrackInfo rhs) -> {
             if (Objects.equals(lhs, rhs)) {
                 return 0;
@@ -68,35 +59,26 @@
             if (rhs == null) {
                 return 1;
             }
-            // Find the first language that matches the lhs and rhs tracks. The  earlier match is
-            // better. If there is no match set the index to the size of the language list since
-            // its the worst match.
-            int lhsLangIndex =
-                    Iterables.indexOf(languages, s -> Utils.isEqualLanguage(lhs.getLanguage(), s));
-            if (lhsLangIndex == -1) {
-                lhsLangIndex = languages.size();
-            }
-            int rhsLangIndex =
-                    Iterables.indexOf(languages, s -> Utils.isEqualLanguage(rhs.getLanguage(), s));
-            if (rhsLangIndex == -1) {
-                rhsLangIndex = languages.size();
-            }
-            if (lhsLangIndex != rhsLangIndex) {
-                // Return the track with lower index as best
-                return Integer.compare(rhsLangIndex, lhsLangIndex);
-            }
-            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 if (lhsCountMatch || rhsCountMatch) {
-                return Boolean.compare(lhsCountMatch, rhsCountMatch);
+            // 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 lhsLangMatch =
+                    language == null || Utils.isEqualLanguage(lhs.getLanguage(), language);
+            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 Boolean.compare(lhsCountMatch, rhsCountMatch);
+                }
             } else {
-                return Integer.compare(lhs.getAudioChannelCount(), rhs.getAudioChannelCount());
+                return Boolean.compare(lhsLangMatch, rhsLangMatch);
             }
         };
     }
@@ -115,20 +97,7 @@
         if (tracks == null) {
             return null;
         }
-        List<String> languages = new ArrayList<>();
-        if (language == null) {
-            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
-                LocaleList locales = LocaleList.getDefault();
-                for (int i = 0; i < locales.size(); i++) {
-                    languages.add(locales.get(i).getLanguage());
-                }
-            } else {
-                languages.add(Locale.getDefault().getLanguage());
-            }
-        } else {
-            languages.add(language);
-        }
-        Comparator<TvTrackInfo> comparator = createComparator(id, languages, channelCount);
+        Comparator<TvTrackInfo> comparator = createComparator(id, language, channelCount);
         TvTrackInfo best = null;
         for (TvTrackInfo track : tracks) {
             if (comparator.compare(track, best) > 0) {
@@ -159,7 +128,11 @@
         if (!TextUtils.isEmpty(track.getLanguage())) {
             language = new Locale(track.getLanguage()).getDisplayName();
         } else {
-            Log.d(TAG, "No language information found for the audio track: " + toString(track));
+            Log.d(
+                TAG,
+                "No language information found for the audio track: "
+                + toString(track)
+            );
         }
 
         StringBuilder metadata = new StringBuilder();
@@ -234,31 +207,31 @@
     public static String toString(TvTrackInfo info) {
         int trackType = info.getType();
         return "TvTrackInfo{"
-                + "type="
-                + trackTypeToString(trackType)
-                + ", id="
-                + info.getId()
-                + ", language="
-                + info.getLanguage()
-                + ", description="
-                + info.getDescription()
-                + (trackType == TvTrackInfo.TYPE_AUDIO
-                        ? (", audioChannelCount="
-                                + info.getAudioChannelCount()
-                                + ", audioSampleRate="
-                                + info.getAudioSampleRate())
-                        : "")
-                + (trackType == TvTrackInfo.TYPE_VIDEO
-                        ? (", videoWidth="
-                                + info.getVideoWidth()
-                                + ", videoHeight="
-                                + info.getVideoHeight()
-                                + ", videoFrameRate="
-                                + info.getVideoFrameRate()
-                                + ", videoPixelAspectRatio="
-                                + info.getVideoPixelAspectRatio())
-                        : "")
-                + "}";
+            + "type="
+            + trackTypeToString(trackType)
+            + ", id="
+            + info.getId()
+            + ", language="
+            + info.getLanguage()
+            + ", description="
+            + info.getDescription()
+            + (trackType == TvTrackInfo.TYPE_AUDIO
+                ?
+                (", audioChannelCount="
+                + info.getAudioChannelCount()
+                + ", audioSampleRate="
+                + info.getAudioSampleRate()) : "")
+            + (trackType == TvTrackInfo.TYPE_VIDEO
+                ?
+                (", videoWidth="
+                + info.getVideoWidth()
+                + ", videoHeight="
+                + info.getVideoHeight()
+                + ", videoFrameRate="
+                + info.getVideoFrameRate()
+                + ", videoPixelAspectRatio="
+                + info.getVideoPixelAspectRatio()) : "")
+            + "}";
     }
 
     private TvTrackInfoUtils() {}
diff --git a/src/com/android/tv/util/Utils.java b/src/com/android/tv/util/Utils.java
index c1f9e93..5117373 100644
--- a/src/com/android/tv/util/Utils.java
+++ b/src/com/android/tv/util/Utils.java
@@ -39,19 +39,17 @@
 import android.text.format.DateUtils;
 import android.util.Log;
 import android.view.View;
-
 import com.android.tv.R;
 import com.android.tv.TvSingletons;
 import com.android.tv.common.BaseSingletons;
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.common.util.Clock;
 import com.android.tv.data.GenreItems;
-import com.android.tv.data.ProgramImpl;
+import com.android.tv.data.Program;
 import com.android.tv.data.StreamInfo;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
-
 import java.text.SimpleDateFormat;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Calendar;
 import java.util.Collection;
@@ -326,7 +324,7 @@
                         TvContract.buildChannelUri(channelId), timeMs, timeMs);
         ContentResolver resolver = context.getContentResolver();
 
-        String[] projection = ProgramImpl.PROJECTION;
+        String[] projection = Program.PROJECTION;
         if (TvProviderUtils.checkSeriesIdColumn(context, TvContract.Programs.CONTENT_URI)) {
             if (Utils.isProgramsUri(uri)) {
                 projection =
@@ -336,7 +334,7 @@
         }
         try (Cursor cursor = resolver.query(uri, projection, null, null, null)) {
             if (cursor != null && cursor.moveToNext()) {
-                return ProgramImpl.fromCursor(cursor);
+                return Program.fromCursor(cursor);
             }
         }
         return null;
@@ -605,7 +603,6 @@
     }
 
     /** Returns the label for a given input. Returns the custom label, if any. */
-    @Nullable
     public static String loadLabel(Context context, TvInputInfo input) {
         if (input == null) {
             return null;
@@ -615,7 +612,7 @@
         CharSequence customLabel = inputManager.loadCustomLabel(input);
         String label = (customLabel == null) ? null : customLabel.toString();
         if (TextUtils.isEmpty(label)) {
-            label = inputManager.loadLabel(input);
+            label = inputManager.loadLabel(input).toString();
         }
         return label;
     }
@@ -717,6 +714,33 @@
         return context.createConfigurationContext(config).getText(resourceId);
     }
 
+    /** Checks where there is any internal TV input. */
+    public static boolean hasInternalTvInputs(Context context, boolean tunerInputOnly) {
+        for (TvInputInfo input :
+                TvSingletons.getSingletons(context)
+                        .getTvInputManagerHelper()
+                        .getTvInputInfos(true, tunerInputOnly)) {
+            if (isInternalTvInput(context, input.getId())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /** Returns the internal TV inputs. */
+    public static List<TvInputInfo> getInternalTvInputs(Context context, boolean tunerInputOnly) {
+        List<TvInputInfo> inputs = new ArrayList<>();
+        for (TvInputInfo input :
+                TvSingletons.getSingletons(context)
+                        .getTvInputManagerHelper()
+                        .getTvInputInfos(true, tunerInputOnly)) {
+            if (isInternalTvInput(context, input.getId())) {
+                inputs.add(input);
+            }
+        }
+        return inputs;
+    }
+
     /** Checks whether the input is internal or not. */
     public static boolean isInternalTvInput(Context context, String inputId) {
         ComponentName unflattenInputId = ComponentName.unflattenFromString(inputId);
diff --git a/src/com/android/tv/util/account/AccountHelper.java b/src/com/android/tv/util/account/AccountHelper.java
index d54c2f5..e98b42e 100644
--- a/src/com/android/tv/util/account/AccountHelper.java
+++ b/src/com/android/tv/util/account/AccountHelper.java
@@ -35,11 +35,4 @@
     /** Returns all eligible accounts . */
     @Nullable
     Account getFirstEligibleAccount();
-
-    /**
-     * Initialize the account helper.
-     *
-     * <p>This method is a no op if called more than once.
-     */
-    void init();
 }
diff --git a/src/com/android/tv/util/account/AccountHelperImpl.java b/src/com/android/tv/util/account/AccountHelperImpl.java
index e97cc3f..58fbd27 100644
--- a/src/com/android/tv/util/account/AccountHelperImpl.java
+++ b/src/com/android/tv/util/account/AccountHelperImpl.java
@@ -21,12 +21,8 @@
 import android.content.SharedPreferences;
 import android.preference.PreferenceManager;
 import android.support.annotation.Nullable;
-import com.android.tv.common.dagger.annotations.ApplicationContext;
-import javax.inject.Inject;
-import javax.inject.Singleton;
 
 /** Helper methods for getting and selecting a user account. */
-@Singleton
 public class AccountHelperImpl implements com.android.tv.util.account.AccountHelper {
     private static final String SELECTED_ACCOUNT = "android.tv.livechannels.selected_account";
 
@@ -35,8 +31,7 @@
 
     @Nullable private Account mSelectedAccount;
 
-    @Inject
-    public AccountHelperImpl(@ApplicationContext Context context) {
+    public AccountHelperImpl(Context context) {
         mContext = context.getApplicationContext();
         mDefaultPreferences = PreferenceManager.getDefaultSharedPreferences(mContext);
     }
@@ -103,9 +98,4 @@
                 PreferenceManager.getDefaultSharedPreferences(mContext);
         defaultPreferences.edit().putString(SELECTED_ACCOUNT, account.name).commit();
     }
-
-    @Override
-    public void init() {
-        // do nothing.
-    }
 }
diff --git a/src/com/android/tv/util/images/ImageLoader.java b/src/com/android/tv/util/images/ImageLoader.java
index e026f26..d2ad0eb 100644
--- a/src/com/android/tv/util/images/ImageLoader.java
+++ b/src/com/android/tv/util/images/ImageLoader.java
@@ -29,13 +29,9 @@
 import android.support.annotation.WorkerThread;
 import android.util.ArraySet;
 import android.util.Log;
-
-import androidx.tvprovider.media.tv.TvContractCompat.PreviewPrograms;
-
 import com.android.tv.R;
 import com.android.tv.common.concurrent.NamedThreadFactory;
 import com.android.tv.util.images.BitmapUtils.ScaledBitmapInfo;
-
 import java.lang.ref.WeakReference;
 import java.util.HashMap;
 import java.util.Map;
@@ -168,8 +164,8 @@
      * @return {@code true} if the load is complete and the callback is executed.
      */
     @UiThread
-    public static <T> boolean loadBitmap(
-            Context context, String uriString, ImageLoaderCallback<T> callback) {
+    public static boolean loadBitmap(
+            Context context, String uriString, ImageLoaderCallback callback) {
         return loadBitmap(context, uriString, Integer.MAX_VALUE, Integer.MAX_VALUE, callback);
     }
 
@@ -182,12 +178,12 @@
      * @return {@code true} if the load is complete and the callback is executed.
      */
     @UiThread
-    public static <T> boolean loadBitmap(
+    public static boolean loadBitmap(
             Context context,
             String uriString,
             int maxWidth,
             int maxHeight,
-            ImageLoaderCallback<T> callback) {
+            ImageLoaderCallback callback) {
         if (DEBUG) {
             Log.d(TAG, "loadBitmap() " + uriString);
         }
@@ -195,12 +191,12 @@
                 context, uriString, maxWidth, maxHeight, callback, IMAGE_THREAD_POOL_EXECUTOR);
     }
 
-    private static <T> boolean doLoadBitmap(
+    private static boolean doLoadBitmap(
             Context context,
             String uriString,
             int maxWidth,
             int maxHeight,
-            ImageLoaderCallback<T> callback,
+            ImageLoaderCallback callback,
             Executor executor) {
         // Check the cache before creating a Task.  The cache will be checked again in doLoadBitmap
         // but checking a cache is much cheaper than creating an new task.
@@ -226,8 +222,7 @@
      * @return {@code true} if the load is complete and the callback is executed.
      */
     @UiThread
-    public static <T> boolean loadBitmap(
-            ImageLoaderCallback<T> callback, LoadBitmapTask<T> loadBitmapTask) {
+    public static boolean loadBitmap(ImageLoaderCallback callback, LoadBitmapTask loadBitmapTask) {
         if (DEBUG) {
             Log.d(TAG, "loadBitmap() " + loadBitmapTask);
         }
@@ -236,8 +231,8 @@
 
     /** @return {@code true} if the load is complete and the callback is executed. */
     @UiThread
-    private static <T> boolean doLoadBitmap(
-            ImageLoaderCallback<T> callback, Executor executor, LoadBitmapTask<T> loadBitmapTask) {
+    private static boolean doLoadBitmap(
+            ImageLoaderCallback callback, Executor executor, LoadBitmapTask loadBitmapTask) {
         ScaledBitmapInfo bitmapInfo = loadBitmapTask.getFromCache();
         boolean needToReload = loadBitmapTask.isReloadNeeded();
         if (bitmapInfo != null && !needToReload) {
@@ -272,11 +267,11 @@
      *
      * <p>Implement {@link #doGetBitmapInBackground} to do the actual loading.
      */
-    public abstract static class LoadBitmapTask<T> extends AsyncTask<Void, Void, ScaledBitmapInfo> {
+    public abstract static class LoadBitmapTask extends AsyncTask<Void, Void, ScaledBitmapInfo> {
         protected final Context mAppContext;
         protected final int mMaxWidth;
         protected final int mMaxHeight;
-        private final Set<ImageLoaderCallback<T>> mCallbacks = new ArraySet<>();
+        private final Set<ImageLoaderCallback> mCallbacks = new ArraySet<>();
         private final ImageCache mImageCache;
         private final String mKey;
 
@@ -358,7 +353,7 @@
         public final void onPostExecute(ScaledBitmapInfo scaledBitmapInfo) {
             if (DEBUG) Log.d(ImageLoader.TAG, "Bitmap is loaded " + mKey);
 
-            for (ImageLoader.ImageLoaderCallback<T> callback : mCallbacks) {
+            for (ImageLoader.ImageLoaderCallback callback : mCallbacks) {
                 callback.onBitmapLoaded(scaledBitmapInfo == null ? null : scaledBitmapInfo.bitmap);
             }
             ImageLoader.sPendingListMap.remove(mKey);
@@ -381,7 +376,7 @@
         }
     }
 
-    private static final class LoadBitmapFromUriTask<T> extends LoadBitmapTask<T> {
+    private static final class LoadBitmapFromUriTask extends LoadBitmapTask {
         private LoadBitmapFromUriTask(
                 Context context,
                 ImageCache imageCache,
@@ -400,7 +395,7 @@
     }
 
     /** Loads and caches the logo for a given {@link TvInputInfo} */
-    public static final class LoadTvInputLogoTask<T> extends LoadBitmapTask<T> {
+    public static final class LoadTvInputLogoTask extends LoadBitmapTask {
         private final TvInputInfo mInfo;
 
         public LoadTvInputLogoTask(Context context, ImageCache cache, TvInputInfo info) {
@@ -419,10 +414,9 @@
         @Override
         public ScaledBitmapInfo doGetBitmapInBackground() {
             Drawable drawable = mInfo.loadIcon(mAppContext);
-            Bitmap bm =
-                    drawable instanceof BitmapDrawable
-                            ? ((BitmapDrawable) drawable).getBitmap()
-                            : BitmapUtils.drawableToBitmap(drawable);
+            Bitmap bm = drawable instanceof BitmapDrawable
+                    ? ((BitmapDrawable) drawable).getBitmap()
+                    : BitmapUtils.drawableToBitmap(drawable);
             return bm == null
                     ? null
                     : BitmapUtils.createScaledBitmapInfo(getKey(), bm, mMaxWidth, mMaxHeight);
@@ -434,46 +428,6 @@
         }
     }
 
-    /**
-     * Calculates Aspect Ratio of Poster Art from Uri.
-     *
-     * <p><b>Note</b> the function will check the cache before loading the bitmap
-     *
-     * @return the Aspect Ratio of the Poster Art.
-     */
-    public static int getAspectRatioFromPosterArtUri(Context context, String uriString) {
-        // Check the cache before loading the bitmap.
-        ImageCache imageCache = ImageCache.getInstance();
-        ScaledBitmapInfo bitmapInfo = imageCache.get(uriString);
-        int bitmapWidth;
-        int bitmapHeight;
-        float bitmapAspectRatio;
-        int aspectRatio;
-        if (bitmapInfo == null) {
-            bitmapInfo =
-                    BitmapUtils.decodeSampledBitmapFromUriString(
-                            context, uriString, Integer.MAX_VALUE, Integer.MAX_VALUE);
-        }
-        bitmapWidth = bitmapInfo.bitmap.getWidth();
-        bitmapHeight = bitmapInfo.bitmap.getHeight();
-        bitmapAspectRatio = (float) bitmapWidth / bitmapHeight;
-        /* Assign nearest aspect ratio from the defined values in Preview Programs */
-        if (bitmapAspectRatio > 0 && bitmapAspectRatio <= 0.6803) {
-            aspectRatio = PreviewPrograms.ASPECT_RATIO_2_3;
-        } else if (bitmapAspectRatio > 0.6803 && bitmapAspectRatio <= 0.8469) {
-            aspectRatio = PreviewPrograms.ASPECT_RATIO_MOVIE_POSTER;
-        } else if (bitmapAspectRatio > 0.8469 && bitmapAspectRatio <= 1.1667) {
-            aspectRatio = PreviewPrograms.ASPECT_RATIO_1_1;
-        } else if (bitmapAspectRatio > 1.1667 && bitmapAspectRatio <= 1.4167) {
-            aspectRatio = PreviewPrograms.ASPECT_RATIO_4_3;
-        } else if (bitmapAspectRatio > 1.4167 && bitmapAspectRatio <= 1.6389) {
-            aspectRatio = PreviewPrograms.ASPECT_RATIO_3_2;
-        } else {
-            aspectRatio = PreviewPrograms.ASPECT_RATIO_16_9;
-        }
-        return aspectRatio;
-    }
-
     private static synchronized Handler getMainHandler() {
         if (sMainHandler == null) {
             sMainHandler = new Handler(Looper.getMainLooper());
diff --git a/tests/common/Android.bp b/tests/common/Android.bp
deleted file mode 100644
index 1abaaf7..0000000
--- a/tests/common/Android.bp
+++ /dev/null
@@ -1,50 +0,0 @@
-//
-// Copyright (C) 2019 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_library {
-    name: "tv-test-common",
-
-    // Include all test java files.
-    srcs: [
-        "src/**/*.java",
-        "src/**/I*.aidl",
-    ],
-
-    static_libs: [
-        "android-support-annotations",
-        "androidx.test.runner",
-        "androidx.test.rules",
-        "tv-guava-android-jar",
-        "mockito-robolectric-prebuilt",
-        "tv-lib-truth",
-        "ub-uiautomator",
-        "Robolectric_all-target",
-    ],
-
-    // Link tv-common as shared library to avoid the problem of initialization of the constants
-    libs: [
-        "tv-common",
-        "LiveTv",
-    ],
-
-    sdk_version: "system_current",
-
-    resource_dirs: ["res"],
-    aidl: {
-        local_include_dirs: ["src"],
-    },
-
-}
diff --git a/tests/common/Android.mk b/tests/common/Android.mk
index e434e12..7a111d0 100644
--- a/tests/common/Android.mk
+++ b/tests/common/Android.mk
@@ -1,23 +1,29 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE := tv-test-common-robo
-
+# Include all test java files.
 LOCAL_SRC_FILES := \
-    $(call all-java-files-under, src/com/android/tv/testing/robo) \
-    $(call all-java-files-under, src/com/android/tv/testing/shadows)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+    $(call all-java-files-under, src) \
+    $(call all-Iaidl-files-under, src)
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
-    robolectric_android-all-stub \
-    Robolectric_all-target \
-    mockito-robolectric-prebuilt \
-    tv-test-common \
+    android-support-annotations \
+    androidx.test.runner \
+    androidx.test.rules \
+    tv-guava-android-jar \
+    mockito-target \
+    tv-lib-truth \
+    ub-uiautomator \
+
+# Link tv-common as shared library to avoid the problem of initialization of the constants
+LOCAL_JAVA_LIBRARIES := tv-common
 
 LOCAL_INSTRUMENTATION_FOR := LiveTv
-
+LOCAL_MODULE := tv-test-common
 LOCAL_MODULE_TAGS := optional
 LOCAL_SDK_VERSION := system_current
 
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+LOCAL_AIDL_INCLUDES += $(LOCAL_PATH)/src
+
 include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tests/common/AndroidManifest.xml b/tests/common/AndroidManifest.xml
index ec9614d..3a769a8 100644
--- a/tests/common/AndroidManifest.xml
+++ b/tests/common/AndroidManifest.xml
@@ -18,6 +18,6 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="com.android.tv.testing"
           android:versionCode="1">
-  <uses-sdk android:targetSdkVersion="28" android:minSdkVersion="23"/>
+  <uses-sdk android:targetSdkVersion="27" android:minSdkVersion="23"/>
     <application />
 </manifest>
diff --git a/tests/common/src/com/android/tv/testing/ChannelNumberSubject.java b/tests/common/src/com/android/tv/testing/ChannelNumberSubject.java
index 1592897..ba4662e 100644
--- a/tests/common/src/com/android/tv/testing/ChannelNumberSubject.java
+++ b/tests/common/src/com/android/tv/testing/ChannelNumberSubject.java
@@ -16,8 +16,6 @@
 
 package com.android.tv.testing;
 
-import static com.google.common.truth.Fact.simpleFact;
-
 import android.support.annotation.Nullable;
 import com.android.tv.data.ChannelNumber;
 import com.google.common.truth.ComparableSubject;
@@ -26,7 +24,8 @@
 import com.google.common.truth.Truth;
 
 /** Propositions for {@link ChannelNumber} subjects. */
-public final class ChannelNumberSubject extends ComparableSubject {
+public final class ChannelNumberSubject
+        extends ComparableSubject<ChannelNumberSubject, ChannelNumber> {
     private static final Subject.Factory<ChannelNumberSubject, ChannelNumber> FACTORY =
             ChannelNumberSubject::new;
 
@@ -38,30 +37,30 @@
         return Truth.assertAbout(channelNumbers()).that(actual);
     }
 
-  private final ChannelNumber actual;
-
-  public ChannelNumberSubject(FailureMetadata failureMetadata, @Nullable ChannelNumber subject) {
-    super(failureMetadata, subject);
-    this.actual = subject;
+    public ChannelNumberSubject(FailureMetadata failureMetadata, @Nullable ChannelNumber subject) {
+        super(failureMetadata, subject);
     }
 
     public void displaysAs(int major) {
-    if (!actual.majorNumber.equals(Integer.toString(major)) || actual.hasDelimiter) {
-            failWithActual("expected to display as", major);
+        if (!getSubject().majorNumber.equals(Integer.toString(major))
+                || getSubject().hasDelimiter) {
+            fail("displaysAs", major);
         }
     }
 
     public void displaysAs(int major, int minor) {
-    if (!actual.majorNumber.equals(Integer.toString(major))
-        || !actual.minorNumber.equals(Integer.toString(minor))
-        || !actual.hasDelimiter) {
-            failWithActual("expected to display as", major + "-" + minor);
+        if (!getSubject().majorNumber.equals(Integer.toString(major))
+                || !getSubject().minorNumber.equals(Integer.toString(minor))
+                || !getSubject().hasDelimiter) {
+            fail("displaysAs", major + "-" + minor);
         }
     }
 
     public void isEmpty() {
-    if (!actual.majorNumber.isEmpty() || !actual.minorNumber.isEmpty() || actual.hasDelimiter) {
-            failWithActual(simpleFact("expected to be empty"));
+        if (!getSubject().majorNumber.isEmpty()
+                || !getSubject().minorNumber.isEmpty()
+                || getSubject().hasDelimiter) {
+            fail("isEmpty");
         }
     }
 }
diff --git a/tests/common/src/com/android/tv/testing/ComparatorTester.java b/tests/common/src/com/android/tv/testing/ComparatorTester.java
index 01c3964..6ebd8b4 100644
--- a/tests/common/src/com/android/tv/testing/ComparatorTester.java
+++ b/tests/common/src/com/android/tv/testing/ComparatorTester.java
@@ -16,198 +16,128 @@
 
 package com.android.tv.testing;
 
-import static com.google.common.truth.Truth.assertWithMessage;
-import static com.google.common.truth.Truth.assert_;
+import static junit.framework.Assert.assertEquals;
 
-import android.support.annotation.Nullable;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-import com.google.common.primitives.Ints;
-
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.Comparator;
 import java.util.List;
 
 /**
- * Tests that a given {@link Comparator} (or the implementation of {@link Comparable}) is correct.
- * To use, repeatedly call {@link #addEqualityGroup(Object...)} with sets of objects that should be
- * equal. The calls to {@link #addEqualityGroup(Object...)} must be made in sorted order. Then call
- * {@link #testCompare()} to test the comparison. For example:
+ * Tester for {@link Comparator} relationships between groups of T.
+ *
+ * <p>To use, create a new {@link ComparatorTester} and add comparable groups where each group
+ * contains objects that are {@link Comparator#compare(Object, Object)} == 0 to each other. Groups
+ * are added in order asserting that all earlier groups have compare < 0 for all later groups.
  *
  * <pre>{@code
- * new ComparatorTester()
- *     .addEqualityGroup(1)
- *     .addEqualityGroup(2)
- *     .addEqualityGroup(3)
- *     .testCompare();
+ * ComparatorTester
+ *     .withoutEqualsTest(String.CASE_INSENSITIVE_ORDER)
+ *     .addComparableGroup("Hello", "HELLO")
+ *     .addComparableGroup("World", "wORLD")
+ *     .addComparableGroup("ZEBRA")
+ *     .test();
  * }</pre>
  *
- * <p>By default, a {@code Comparator} is not tested for compatibility with {@link
- * Object#equals(Object)}. If that is desired, use the {link #requireConsistencyWithEquals()} to
- * explicitly activate the check. For example:
- *
- * <pre>{@code
- * new ComparatorTester(Comparator.naturalOrder())
- *     .requireConsistencyWithEquals()
- *     .addEqualityGroup(1)
- *     .addEqualityGroup(2)
- *     .addEqualityGroup(3)
- *     .testCompare();
- * }</pre>
- *
- * <p>If for some reason you need to suppress the compatibility check when testing a {@code
- * Comparable}, use the {link #permitInconsistencyWithEquals()} to explicitly deactivate the check.
- * For example:
- *
- * <pre>{@code
- * new ComparatorTester()
- *     .permitInconsistencyWithEquals()
- *     .addEqualityGroup(1)
- *     .addEqualityGroup(2)
- *     .addEqualityGroup(3)
- *     .testCompare();
- * }</pre>
+ * @param <T> the type of objects to compare.
  */
-public class ComparatorTester {
-    @SuppressWarnings({"unchecked", "rawtypes"})
-    @Nullable
-    private final Comparator comparator;
+public class ComparatorTester<T> {
 
-    /** The items that we are checking, stored as a sorted set of equivalence classes. */
-    private final List<List<Object>> equalityGroups;
+    private final List<List<T>> listOfGroups = new ArrayList<>();
 
-    /** Whether to enforce a.equals(b) == (a.compareTo(b) == 0) */
-    private boolean testForEqualsCompatibility;
+    private final Comparator<T> comparator;
 
-    /**
-     * Creates a new instance that tests the order of objects using the natural order (as defined by
-     * {@link Comparable}).
-     */
-    public ComparatorTester() {
-        this(null);
+    public static <T> ComparatorTester<T> withoutEqualsTest(Comparator<T> comparator) {
+        return new ComparatorTester<>(comparator);
     }
 
-    /**
-     * Creates a new instance that tests the order of objects using the given comparator. Or, if the
-     * comparator is {@code null}, the natural ordering (as defined by {@link Comparable})
-     */
-    public ComparatorTester(@Nullable Comparator<?> comparator) {
-        this.equalityGroups = Lists.newArrayList();
+    private ComparatorTester(Comparator<T> comparator) {
         this.comparator = comparator;
-        this.testForEqualsCompatibility = (this.comparator == null);
     }
 
-    /**
-     * Activates enforcement of {@code a.equals(b) == (a.compareTo(b) == 0)}. This is off by default
-     * when testing {@link Comparator}s, but can be turned on if required.
-     */
-    public ComparatorTester requireConsistencyWithEquals() {
-        testForEqualsCompatibility = true;
+    @SafeVarargs
+    public final ComparatorTester<T> addComparableGroup(T... items) {
+        listOfGroups.add(Arrays.asList(items));
         return this;
     }
 
-    /**
-     * Deactivates enforcement of {@code a.equals(b) == (a.compareTo(b) == 0)}. This is on by
-     * default when testing {@link Comparable}s, but can be turned off if required.
-     */
-    public ComparatorTester permitInconsistencyWithEquals() {
-        testForEqualsCompatibility = false;
-        return this;
-    }
-
-    /**
-     * Adds a set of objects to the test which should all compare as equal. All of the elements in
-     * {@code objects} must be greater than any element of {@code objects} in a previous call to
-     * {@link #addEqualityGroup(Object...)}.
-     *
-     * @return {@code this} (to allow chaining of calls)
-     */
-    public ComparatorTester addEqualityGroup(Object... objects) {
-        Preconditions.checkNotNull(objects);
-        Preconditions.checkArgument(objects.length > 0, "Array must not be empty");
-        equalityGroups.add(ImmutableList.copyOf(objects));
-        return this;
-    }
-
-    @SuppressWarnings({"unchecked"})
-    private int compare(Object a, Object b) {
-        int compareValue;
-        if (comparator == null) {
-            compareValue = ((Comparable<Object>) a).compareTo(b);
-        } else {
-            compareValue = comparator.compare(a, b);
+    public void test() {
+        for (int i = 0; i < listOfGroups.size(); i++) {
+            List<T> currentGroup = listOfGroups.get(i);
+            for (int j = 0; j < i; j++) {
+                List<T> lhs = listOfGroups.get(j);
+                assertOrder(i, j, lhs, currentGroup);
+            }
+            assertZero(currentGroup);
+            for (int j = i + 1; j < listOfGroups.size(); j++) {
+                List<T> rhs = listOfGroups.get(j);
+                assertOrder(i, j, currentGroup, rhs);
+            }
         }
-        return compareValue;
+        // TODO: also test equals
     }
 
-    public final void testCompare() {
-        doTestEquivalanceGroupOrdering();
-        if (testForEqualsCompatibility) {
-            doTestEqualsCompatibility();
-        }
+    private void assertOrder(int less, int more, List<T> lessGroup, List<T> moreGroup) {
+        assertLess(less, more, lessGroup, moreGroup);
+        assertMore(more, less, moreGroup, lessGroup);
     }
 
-    private final void doTestEquivalanceGroupOrdering() {
-        for (int referenceIndex = 0; referenceIndex < equalityGroups.size(); referenceIndex++) {
-            for (Object reference : equalityGroups.get(referenceIndex)) {
-                testNullCompare(reference);
-                testClassCast(reference);
-                for (int otherIndex = 0; otherIndex < equalityGroups.size(); otherIndex++) {
-                    for (Object other : equalityGroups.get(otherIndex)) {
-                        assertWithMessage("compare(%s, %s)", reference, other)
-                                .that(Integer.signum(compare(reference, other)))
-                                .isEqualTo(
-                                        Integer.signum(Ints.compare(referenceIndex, otherIndex)));
-                    }
-                }
+    private void assertLess(
+            int left, int right, Collection<T> leftGroup, Collection<T> rightGroup) {
+        int leftSub = 0;
+        for (T leftItem : leftGroup) {
+            int rightSub = 0;
+            for (T rightItem : rightGroup) {
+                String leftName = "Item[" + left + "," + (leftSub++) + "]";
+                String rName = "Item[" + right + "," + (rightSub++) + "]";
+                assertEquals(
+                        leftName
+                                + " "
+                                + leftItem
+                                + " compareTo "
+                                + rName
+                                + " "
+                                + rightItem
+                                + " is <0",
+                        true,
+                        comparator.compare(leftItem, rightItem) < 0);
             }
         }
     }
 
-    private final void doTestEqualsCompatibility() {
-        for (List<Object> referenceGroup : equalityGroups) {
-            for (Object reference : referenceGroup) {
-                for (List<Object> otherGroup : equalityGroups) {
-                    for (Object other : otherGroup) {
-                        assertWithMessage(
-                                        "Testing equals() for compatibility with"
-                                            + " compare()/compareTo(), add a call to"
-                                            + " doNotRequireEqualsCompatibility() if this is not"
-                                            + " required")
-                                .withMessage("%s.equals(%s)", reference, other)
-                                .that(reference.equals(other))
-                                .isEqualTo(compare(reference, other) == 0);
-                    }
-                }
+    private void assertMore(
+            int left, int right, Collection<T> leftGroup, Collection<T> rightGroup) {
+        int leftSub = 0;
+        for (T leftItem : leftGroup) {
+            int rightSub = 0;
+            for (T rightItem : rightGroup) {
+                String leftName = "Item[" + left + "," + (leftSub++) + "]";
+                String rName = "Item[" + right + "," + (rightSub++) + "]";
+                assertEquals(
+                        leftName
+                                + " "
+                                + leftItem
+                                + " compareTo "
+                                + rName
+                                + " "
+                                + rightItem
+                                + " is >0",
+                        true,
+                        comparator.compare(leftItem, rightItem) > 0);
             }
         }
     }
 
-    private void testNullCompare(Object obj) {
-        // Comparator does not require any specific behavior for null.
-        if (comparator == null) {
-            try {
-                compare(obj, null);
-                assert_().fail("Expected NullPointerException in %s.compare(null)", obj);
-            } catch (NullPointerException expected) {
-                // TODO(cpovirk): Consider accepting JavaScriptException under GWT
+    private void assertZero(Collection<T> group) {
+        // Test everything against everything in both directions, including against itself.
+        for (T leftItem : group) {
+            for (T rightItem : group) {
+                assertEquals(
+                        leftItem + " compareTo " + rightItem,
+                        0,
+                        comparator.compare(leftItem, rightItem));
             }
         }
     }
-
-    @SuppressWarnings("unchecked")
-    private void testClassCast(Object obj) {
-        if (comparator == null) {
-            try {
-                compare(obj, ICanNotBeCompared.INSTANCE);
-                assert_().fail("Expected ClassCastException in %s.compareTo(otherObject)", obj);
-            } catch (ClassCastException expected) {
-            }
-        }
-    }
-
-    private static final class ICanNotBeCompared {
-        static final ComparatorTester.ICanNotBeCompared INSTANCE = new ICanNotBeCompared();
-    }
 }
diff --git a/tests/common/src/com/android/tv/testing/EpgTestData.java b/tests/common/src/com/android/tv/testing/EpgTestData.java
index d22bd28..362f336 100644
--- a/tests/common/src/com/android/tv/testing/EpgTestData.java
+++ b/tests/common/src/com/android/tv/testing/EpgTestData.java
@@ -18,17 +18,13 @@
 
 import com.android.tv.data.ChannelImpl;
 import com.android.tv.data.Lineup;
-import com.android.tv.data.ProgramImpl;
+import com.android.tv.data.Program;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
-import com.android.tv.testing.fakes.FakeClock;
-
 import com.google.common.base.Function;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableListMultimap;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.ListMultimap;
-
 import java.util.concurrent.TimeUnit;
 
 /** EPG data for use in tests. */
@@ -79,14 +75,14 @@
     // Start and end time may be negative meaning they happen before "now".
 
     public static final Program PROGRAM_1 =
-            new ProgramImpl.Builder()
+            new Program.Builder()
                     .setTitle("Program 1")
                     .setStartTimeUtcMillis(0)
                     .setEndTimeUtcMillis(TimeUnit.MINUTES.toMillis(30))
                     .build();
 
     public static final Program PROGRAM_2 =
-            new ProgramImpl.Builder()
+            new Program.Builder()
                     .setTitle("Program 2")
                     .setStartTimeUtcMillis(TimeUnit.MINUTES.toMillis(30))
                     .setEndTimeUtcMillis(TimeUnit.MINUTES.toMillis(60))
@@ -195,7 +191,7 @@
                 new Function<Program, Program>() {
                     @Override
                     public Program apply(Program p) {
-                        return new ProgramImpl.Builder(p)
+                        return new Program.Builder(p)
                                 .setStartTimeUtcMillis(p.getStartTimeUtcMillis() + time)
                                 .setEndTimeUtcMillis(p.getEndTimeUtcMillis() + time)
                                 .build();
diff --git a/tests/common/src/com/android/tv/testing/fakes/FakeClock.java b/tests/common/src/com/android/tv/testing/FakeClock.java
similarity index 98%
rename from tests/common/src/com/android/tv/testing/fakes/FakeClock.java
rename to tests/common/src/com/android/tv/testing/FakeClock.java
index adef3cd..f594193 100644
--- a/tests/common/src/com/android/tv/testing/fakes/FakeClock.java
+++ b/tests/common/src/com/android/tv/testing/FakeClock.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.tv.testing.fakes;
+package com.android.tv.testing;
 
 import com.android.tv.common.util.Clock;
 import java.util.concurrent.TimeUnit;
diff --git a/tests/common/src/com/android/tv/testing/FakeEpgReader.java b/tests/common/src/com/android/tv/testing/FakeEpgReader.java
index 24afe8e..fb35c65 100644
--- a/tests/common/src/com/android/tv/testing/FakeEpgReader.java
+++ b/tests/common/src/com/android/tv/testing/FakeEpgReader.java
@@ -19,17 +19,13 @@
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.util.Range;
-
 import com.android.tv.data.ChannelImpl;
 import com.android.tv.data.ChannelNumber;
 import com.android.tv.data.Lineup;
-import com.android.tv.data.ProgramImpl;
+import com.android.tv.data.Program;
 import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
 import com.android.tv.data.epg.EpgReader;
 import com.android.tv.dvr.data.SeriesInfo;
-import com.android.tv.testing.fakes.FakeClock;
-
 import com.google.common.base.Function;
 import com.google.common.base.Predicate;
 import com.google.common.collect.ImmutableList;
@@ -37,7 +33,6 @@
 import com.google.common.collect.Iterables;
 import com.google.common.collect.LinkedListMultimap;
 import com.google.common.collect.ListMultimap;
-
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
@@ -149,7 +144,7 @@
             @Nullable
             @Override
             public Program apply(@Nullable Program program) {
-                return new ProgramImpl.Builder(program)
+                return new Program.Builder(program)
                         .setChannelId(channel.getChannel().getId())
                         .setPackageName(channel.getChannel().getPackageName())
                         .build();
diff --git a/tests/common/src/com/android/tv/testing/FakeTvInputManagerHelper.java b/tests/common/src/com/android/tv/testing/FakeTvInputManagerHelper.java
index be08385..85bdcf0 100644
--- a/tests/common/src/com/android/tv/testing/FakeTvInputManagerHelper.java
+++ b/tests/common/src/com/android/tv/testing/FakeTvInputManagerHelper.java
@@ -17,14 +17,13 @@
 package com.android.tv.testing;
 
 import android.content.Context;
-import com.android.tv.common.flags.impl.DefaultLegacyFlags;
 import com.android.tv.util.TvInputManagerHelper;
 
 /** Fake TvInputManagerHelper. */
 public class FakeTvInputManagerHelper extends TvInputManagerHelper {
 
     public FakeTvInputManagerHelper(Context context) {
-        super(context, new FakeTvInputManager(), DefaultLegacyFlags.DEFAULT);
+        super(context, new FakeTvInputManager());
     }
 
     public FakeTvInputManager getFakeTvInputManager() {
diff --git a/tests/common/src/com/android/tv/testing/fakes/FakeTvProvider.java b/tests/common/src/com/android/tv/testing/FakeTvProvider.java
similarity index 99%
rename from tests/common/src/com/android/tv/testing/fakes/FakeTvProvider.java
rename to tests/common/src/com/android/tv/testing/FakeTvProvider.java
index 36e97bc..20903c6 100644
--- a/tests/common/src/com/android/tv/testing/fakes/FakeTvProvider.java
+++ b/tests/common/src/com/android/tv/testing/FakeTvProvider.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package com.android.tv.testing.fakes;
+package com.android.tv.testing;
 
 import android.annotation.SuppressLint;
 import android.content.ContentProvider;
@@ -54,7 +54,7 @@
 import androidx.tvprovider.media.tv.TvContractCompat.Programs.Genres;
 import androidx.tvprovider.media.tv.TvContractCompat.RecordedPrograms;
 import androidx.tvprovider.media.tv.TvContractCompat.WatchNextPrograms;
-import com.android.tv.common.util.sql.SqlParams;
+import com.android.tv.util.SqlParams;
 import java.io.ByteArrayOutputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
diff --git a/tests/common/src/com/android/tv/testing/TestSingletonApp.java b/tests/common/src/com/android/tv/testing/TestSingletonApp.java
index e233d95..f1a98ff 100644
--- a/tests/common/src/com/android/tv/testing/TestSingletonApp.java
+++ b/tests/common/src/com/android/tv/testing/TestSingletonApp.java
@@ -19,23 +19,25 @@
 import android.app.Application;
 import android.media.tv.TvInputManager;
 import android.os.AsyncTask;
-
 import com.android.tv.InputSessionManager;
 import com.android.tv.MainActivityWrapper;
 import com.android.tv.TvSingletons;
 import com.android.tv.analytics.Analytics;
 import com.android.tv.analytics.Tracker;
 import com.android.tv.common.BaseApplication;
+import com.android.tv.common.experiments.ExperimentLoader;
 import com.android.tv.common.flags.impl.DefaultBackendKnobsFlags;
 import com.android.tv.common.flags.impl.DefaultCloudEpgFlags;
+import com.android.tv.common.flags.impl.DefaultConcurrentDvrPlaybackFlags;
+import com.android.tv.common.flags.impl.DefaultTunerFlags;
 import com.android.tv.common.flags.impl.DefaultUiFlags;
-import com.android.tv.common.flags.impl.SettableFlagsModule;
 import com.android.tv.common.recording.RecordingStorageStatusManager;
 import com.android.tv.common.singletons.HasSingletons;
 import com.android.tv.common.util.Clock;
 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.data.epg.EpgReader;
 import com.android.tv.dvr.DvrDataManager;
 import com.android.tv.dvr.DvrManager;
@@ -45,38 +47,47 @@
 import com.android.tv.perf.PerformanceMonitor;
 import com.android.tv.perf.stub.StubPerformanceMonitor;
 import com.android.tv.testing.dvr.DvrDataManagerInMemoryImpl;
-import com.android.tv.testing.fakes.FakeClock;
 import com.android.tv.testing.testdata.TestData;
 import com.android.tv.tuner.singletons.TunerSingletons;
+import com.android.tv.tuner.source.TsDataSourceManager;
+import com.android.tv.tuner.source.TunerTsStreamerManager;
+import com.android.tv.tuner.tvinput.factory.TunerSessionFactory;
+import com.android.tv.tuner.tvinput.factory.TunerSessionFactoryImpl;
 import com.android.tv.tunerinputcontroller.BuiltInTunerManager;
-import com.android.tv.util.AsyncDbTask.DbExecutor;
 import com.android.tv.util.SetupUtils;
 import com.android.tv.util.TvInputManagerHelper;
-
+import com.android.tv.util.account.AccountHelper;
 import com.google.common.base.Optional;
-
-import dagger.Lazy;
-
 import java.util.concurrent.Executor;
+import javax.inject.Provider;
 
-/** Test application for TV app. */
+/** Test application for Live TV. */
 public class TestSingletonApp extends Application
         implements TvSingletons, TunerSingletons, HasSingletons<TvSingletons> {
     public final FakeClock fakeClock = FakeClock.createWithCurrentTime();
     public final FakeEpgReader epgReader = new FakeEpgReader(fakeClock);
     public final FakeEpgFetcher epgFetcher = new FakeEpgFetcher();
-    public final SettableFlagsModule flagsModule = new SettableFlagsModule();
 
     public FakeTvInputManagerHelper tvInputManagerHelper;
     public SetupUtils setupUtils;
     public DvrManager dvrManager;
     public DvrDataManager mDvrDataManager;
-    @DbExecutor public Executor dbExecutor = AsyncTask.SERIAL_EXECUTOR;
 
-    private final Lazy<EpgReader> mEpgReaderProvider = () -> epgReader;
+    private final Provider<EpgReader> mEpgReaderProvider = SingletonProvider.create(epgReader);
     private final Optional<BuiltInTunerManager> mBuiltInTunerManagerOptional = Optional.absent();
-
-    private final PerformanceMonitor mPerformanceMonitor = new StubPerformanceMonitor();
+    private final DefaultBackendKnobsFlags mBackendKnobs = new DefaultBackendKnobsFlags();
+    private final DefaultCloudEpgFlags mCloudEpgFlags = new DefaultCloudEpgFlags();
+    private final DefaultUiFlags mUiFlags = new DefaultUiFlags();
+    private final DefaultConcurrentDvrPlaybackFlags mConcurrentDvrPlaybackFlags =
+            new DefaultConcurrentDvrPlaybackFlags();
+    private final TsDataSourceManager.Factory mTsDataSourceManagerFactory =
+            new TsDataSourceManager.Factory(() -> new TunerTsStreamerManager(null));
+    private final TunerSessionFactoryImpl mTunerSessionFactory =
+            new TunerSessionFactoryImpl(
+                    new DefaultTunerFlags(),
+                    mConcurrentDvrPlaybackFlags,
+                    mTsDataSourceManagerFactory);
+    private PerformanceMonitor mPerformanceMonitor;
     private ChannelDataManager mChannelDataManager;
 
     @Override
@@ -85,9 +96,7 @@
         tvInputManagerHelper = new FakeTvInputManagerHelper(this);
         setupUtils = new SetupUtils(this, mBuiltInTunerManagerOptional);
         tvInputManagerHelper.start();
-        mChannelDataManager =
-                new ChannelDataManager(
-                        this, tvInputManagerHelper, dbExecutor, getContentResolver());
+        mChannelDataManager = new ChannelDataManager(this, tvInputManagerHelper);
         mChannelDataManager.start();
         mDvrDataManager = new DvrDataManagerInMemoryImpl(this, fakeClock);
         // HACK reset the singleton for tests
@@ -115,11 +124,21 @@
     }
 
     @Override
+    public boolean isChannelDataManagerLoadFinished() {
+        return false;
+    }
+
+    @Override
     public ProgramDataManager getProgramDataManager() {
         return null;
     }
 
     @Override
+    public boolean isProgramDataManagerCurrentProgramsLoadFinished() {
+        return false;
+    }
+
+    @Override
     public PreviewDataManager getPreviewDataManager() {
         return null;
     }
@@ -165,11 +184,16 @@
     }
 
     @Override
-    public Lazy<EpgReader> providesEpgReader() {
+    public Provider<EpgReader> providesEpgReader() {
         return mEpgReaderProvider;
     }
 
     @Override
+    public EpgFetcher getEpgFetcher() {
+        return epgFetcher;
+    }
+
+    @Override
     public SetupUtils getSetupUtils() {
         return setupUtils;
     }
@@ -180,11 +204,21 @@
     }
 
     @Override
+    public ExperimentLoader getExperimentLoader() {
+        return new ExperimentLoader();
+    }
+
+    @Override
     public MainActivityWrapper getMainActivityWrapper() {
         return null;
     }
 
     @Override
+    public AccountHelper getAccountHelper() {
+        return null;
+    }
+
+    @Override
     public Clock getClock() {
         return fakeClock;
     }
@@ -201,6 +235,9 @@
 
     @Override
     public PerformanceMonitor getPerformanceMonitor() {
+        if (mPerformanceMonitor == null) {
+            mPerformanceMonitor = new StubPerformanceMonitor();
+        }
         return mPerformanceMonitor;
     }
 
@@ -211,22 +248,22 @@
 
     @Override
     public Executor getDbExecutor() {
-        return dbExecutor;
+        return AsyncTask.SERIAL_EXECUTOR;
     }
 
     @Override
     public DefaultBackendKnobsFlags getBackendKnobs() {
-        return flagsModule.backendKnobsFlags;
+        return mBackendKnobs;
     }
 
     @Override
     public DefaultCloudEpgFlags getCloudEpgFlags() {
-        return flagsModule.cloudEpgFlags;
+        return mCloudEpgFlags;
     }
 
     @Override
     public DefaultUiFlags getUiFlags() {
-        return flagsModule.uiFlags;
+        return mUiFlags;
     }
 
     @Override
@@ -235,6 +272,15 @@
     }
 
     @Override
+    public DefaultConcurrentDvrPlaybackFlags getConcurrentDvrPlaybackFlags() {
+        return mConcurrentDvrPlaybackFlags;
+    }
+
+    public TunerSessionFactory getTunerSessionFactory() {
+        return mTunerSessionFactory;
+    }
+
+    @Override
     public TvSingletons singletons() {
         return this;
     }
diff --git a/tests/common/src/com/android/tv/testing/constants/ConfigConstants.java b/tests/common/src/com/android/tv/testing/constants/ConfigConstants.java
index 944d539..890c51e 100644
--- a/tests/common/src/com/android/tv/testing/constants/ConfigConstants.java
+++ b/tests/common/src/com/android/tv/testing/constants/ConfigConstants.java
@@ -23,8 +23,6 @@
 
     public static final String MANIFEST = "vendor/unbundled_google/packages/TV/AndroidManifest.xml";
     public static final int SDK = Build.VERSION_CODES.M;
-    public static final int MIN_SDK = Build.VERSION_CODES.M;
-    public static final int MAX_SDK = Build.VERSION_CODES.P;
 
     private ConfigConstants() {}
 }
diff --git a/tests/common/src/com/android/tv/testing/robo/ContentProviders.java b/tests/common/src/com/android/tv/testing/robo/ContentProviders.java
deleted file mode 100644
index aaaa11d..0000000
--- a/tests/common/src/com/android/tv/testing/robo/ContentProviders.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2018 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.testing.robo;
-
-import android.content.ContentProvider;
-import android.content.pm.ProviderInfo;
-import org.robolectric.Robolectric;
-import org.robolectric.android.controller.ContentProviderController;
-import org.robolectric.shadows.ShadowContentResolver;
-
-/** Static utilities for using content providers in tests. */
-public final class ContentProviders {
-
-    /** Builds creates and register a ContentProvider with the given authority. */
-    public static <T extends ContentProvider> T register(Class<T> providerClass, String authority) {
-        ProviderInfo info = new ProviderInfo();
-        info.authority = authority;
-        ContentProviderController<T> contentProviderController =
-                Robolectric.buildContentProvider(providerClass);
-        T provider = contentProviderController.create(info).get();
-        provider.onCreate();
-        ShadowContentResolver.registerProviderInternal(authority, provider);
-        return provider;
-    }
-
-    private ContentProviders() {}
-}
diff --git a/tests/common/src/com/android/tv/testing/robo/RobotTestAppHelper.java b/tests/common/src/com/android/tv/testing/robo/RobotTestAppHelper.java
deleted file mode 100644
index ad91f3d..0000000
--- a/tests/common/src/com/android/tv/testing/robo/RobotTestAppHelper.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2018 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.testing.robo;
-
-import android.media.tv.TvContract;
-import com.android.tv.testing.TestSingletonApp;
-import com.android.tv.testing.fakes.FakeTvProvider;
-import com.android.tv.testing.testdata.TestData;
-import java.util.concurrent.TimeUnit;
-import org.robolectric.Robolectric;
-
-/** Static utilities for using {@link TestSingletonApp} in roboletric tests. */
-public final class RobotTestAppHelper {
-
-    public static void loadTestData(TestSingletonApp app, TestData testData) {
-        ContentProviders.register(FakeTvProvider.class, TvContract.AUTHORITY);
-        app.loadTestData(testData, TimeUnit.DAYS.toMillis(1));
-        Robolectric.flushBackgroundThreadScheduler();
-        Robolectric.flushForegroundThreadScheduler();
-    }
-
-    private RobotTestAppHelper() {}
-}
diff --git a/tests/common/src/com/android/tv/testing/shadows/ShadowMediaSession.java b/tests/common/src/com/android/tv/testing/shadows/ShadowMediaSession.java
deleted file mode 100644
index 5a2c41e..0000000
--- a/tests/common/src/com/android/tv/testing/shadows/ShadowMediaSession.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * 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.testing.shadows;
-
-import android.app.PendingIntent;
-import android.content.Context;
-import android.media.MediaMetadata;
-import android.media.session.MediaSession;
-import android.media.session.PlaybackState;
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-
-/** Shadow {@link MediaSession}. */
-@Implements(MediaSession.class)
-public class ShadowMediaSession {
-
-    public MediaSession.Callback mCallback;
-    public PendingIntent mMediaButtonReceiver;
-    public PendingIntent mSessionActivity;
-    public PlaybackState mPlaybackState;
-    public MediaMetadata mMediaMetadata;
-    public int mFlags;
-    public boolean mActive;
-    public boolean mReleased;
-
-    /** Stand-in for the MediaSession constructor with the same parameters. */
-    public void __constructor__(Context context, String tag, int userID) {
-        // This empty method prevents the real MediaSession constructor from being called.
-    }
-
-    @Implementation
-    public void setCallback(MediaSession.Callback callback) {
-        mCallback = callback;
-    }
-
-    @Implementation
-    public void setMediaButtonReceiver(PendingIntent mbr) {
-        mMediaButtonReceiver = mbr;
-    }
-
-    @Implementation
-    public void setSessionActivity(PendingIntent activity) {
-        mSessionActivity = activity;
-    }
-
-    @Implementation
-    public void setPlaybackState(PlaybackState state) {
-        mPlaybackState = state;
-    }
-
-    @Implementation
-    public void setMetadata(MediaMetadata metadata) {
-        mMediaMetadata = metadata;
-    }
-
-    @Implementation
-    public void setFlags(int flags) {
-        mFlags = flags;
-    }
-
-    @Implementation
-    public boolean isActive() {
-        return mActive;
-    }
-
-    @Implementation
-    public void setActive(boolean active) {
-        mActive = active;
-    }
-
-    @Implementation
-    public void release() {
-        mReleased = true;
-    }
-}
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 30fbf37..4b7c1f8 100644
--- a/tests/common/src/com/android/tv/testing/uihelper/LiveChannelsUiDeviceHelper.java
+++ b/tests/common/src/com/android/tv/testing/uihelper/LiveChannelsUiDeviceHelper.java
@@ -30,7 +30,7 @@
 import com.android.tv.testing.utils.Utils;
 import junit.framework.Assert;
 
-/** Helper for testing the TV application. */
+/** Helper for testing the Live TV Application. */
 public class LiveChannelsUiDeviceHelper extends BaseUiDeviceHelper {
     private static final String TAG = "LiveChannelsUiDevice";
     private static final int APPLICATION_START_TIMEOUT_MSEC = 5000;
@@ -56,7 +56,7 @@
         waitForCondition(mUiDevice, Until.hasObject(Constants.TV_VIEW));
 
         Assert.assertTrue(
-                Constants.TV_APP_PACKAGE + " did not start",
+            Constants.TV_APP_PACKAGE + " did not start",
                 mUiDevice.wait(
                         Until.hasObject(By.pkg(Constants.TV_APP_PACKAGE).depth(0)),
                         APPLICATION_START_TIMEOUT_MSEC));
diff --git a/tests/func/AndroidManifest.xml b/tests/func/AndroidManifest.xml
index e60773f..3d7d775 100644
--- a/tests/func/AndroidManifest.xml
+++ b/tests/func/AndroidManifest.xml
@@ -18,7 +18,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.tv.tests.ui" >
 
-    <uses-sdk android:targetSdkVersion="28" android:minSdkVersion="23" />
+    <uses-sdk android:targetSdkVersion="27" android:minSdkVersion="23" />
 
     <instrumentation
         android:name="androidx.test.runner.AndroidJUnitRunner"
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 e24c72f..efc7ecf 100644
--- a/tests/func/src/com/android/tv/tests/ui/PlayControlsRowViewTest.java
+++ b/tests/func/src/com/android/tv/tests/ui/PlayControlsRowViewTest.java
@@ -135,7 +135,7 @@
         controller.pressKeyCode(KeyEvent.KEYCODE_MEDIA_PAUSE);
         controller.menuHelper.assertWaitForMenu();
         assertButtonHasFocus(BUTTON_ID_PLAY_PAUSE);
-        // Press HOME twice to visit the home screen and return to TV app.
+        // Press HOME twice to visit the home screen and return to Live TV.
         controller.pressHome();
         // Wait until home screen is shown.
         controller.waitForIdle();
diff --git a/tests/input/AndroidManifest.xml b/tests/input/AndroidManifest.xml
index 564323a..fa52946 100644
--- a/tests/input/AndroidManifest.xml
+++ b/tests/input/AndroidManifest.xml
@@ -18,7 +18,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.tv.testinput">
 
-    <uses-sdk android:targetSdkVersion="28" android:minSdkVersion="23"/>
+    <uses-sdk android:targetSdkVersion="27" android:minSdkVersion="23"/>
 
      <!-- Required to update or read existing channel and program information in TvProvider. -->
     <uses-permission android:name="com.android.providers.tv.permission.READ_EPG_DATA" />
diff --git a/tests/input/src/com/android/tv/testinput/TestTvInputService.java b/tests/input/src/com/android/tv/testinput/TestTvInputService.java
index d19f455..840587c 100644
--- a/tests/input/src/com/android/tv/testinput/TestTvInputService.java
+++ b/tests/input/src/com/android/tv/testinput/TestTvInputService.java
@@ -53,7 +53,7 @@
     private static final int REFRESH_DELAY_MS = 1000 / 5;
     private static final boolean DEBUG = false;
 
-    // Consider the command delivering time from TV app.
+    // Consider the command delivering time from Live TV.
     private static final long MAX_COMMAND_DELAY = TimeUnit.SECONDS.toMillis(3);
 
     private final TestInputControl mBackend = TestInputControl.getInstance();
diff --git a/tests/jank/AndroidManifest.xml b/tests/jank/AndroidManifest.xml
index 1538851..7c0997a 100644
--- a/tests/jank/AndroidManifest.xml
+++ b/tests/jank/AndroidManifest.xml
@@ -18,7 +18,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.tv.tests.jank" >
 
-    <uses-sdk android:targetSdkVersion="28" android:minSdkVersion="23" />
+    <uses-sdk android:targetSdkVersion="27" android:minSdkVersion="23" />
 
     <instrumentation
             android:name="androidx.test.runner.AndroidJUnitRunner"
diff --git a/tests/jank/src/com/android/tv/tests/jank/Utils.java b/tests/jank/src/com/android/tv/tests/jank/Utils.java
index 57e5f10..4ad0f64 100644
--- a/tests/jank/src/com/android/tv/tests/jank/Utils.java
+++ b/tests/jank/src/com/android/tv/tests/jank/Utils.java
@@ -19,7 +19,7 @@
 import com.android.tv.testing.uihelper.UiDeviceUtils;
 
 public final class Utils {
-    /** TV app process name */
+    /** Live TV process name */
     public static final String LIVE_CHANNELS_PROCESS_NAME = "com.android.tv";
 
     private Utils() {}
diff --git a/tests/robotests/Android.mk b/tests/robotests/Android.mk
deleted file mode 100644
index d5c51b5..0000000
--- a/tests/robotests/Android.mk
+++ /dev/null
@@ -1,76 +0,0 @@
-#############################################################
-# Tv Robolectric test target.                               #
-#############################################################
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := TvRoboTests
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-
-BASE_DIR = src/com/android/tv
-EXCLUDE_FILES := \
-    $(BASE_DIR)/TvActivityTest.java \
-    $(BASE_DIR)/data/epg/EpgFetcherImplTest.java \
-    $(BASE_DIR)/guide/ProgramItemViewTest.java \
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_SRC_FILES := $(filter-out $(EXCLUDE_FILES),$(LOCAL_SRC_FILES))
-
-LOCAL_JAVA_LIBRARIES := \
-    Robolectric_all-target \
-    mockito-robolectric-prebuilt \
-    robolectric_android-all-stub \
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    tv-lib-dagger
-
-LOCAL_STATIC_ANDROID_LIBRARIES := \
-    androidx.test.core \
-    tv-lib-dagger-android \
-    tv-test-common \
-    tv-test-common-robo \
-
-LOCAL_ANNOTATION_PROCESSORS := \
-    tv-lib-dagger-android-processor \
-    tv-lib-dagger-compiler \
-
-LOCAL_ANNOTATION_PROCESSOR_CLASSES := \
-  dagger.internal.codegen.ComponentProcessor,dagger.android.processor.AndroidProcessor
-
-LOCAL_INSTRUMENTATION_FOR := LiveTv
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-#############################################################
-# Tv runner target to run the previous target.              #
-#############################################################
-include $(CLEAR_VARS)
-LOCAL_MODULE := RunTvRoboTests
-
-BASE_DIR = com/android/tv
-EXCLUDE_FILES := \
-    $(BASE_DIR)/MainActivityRoboTest.java \
-    $(BASE_DIR)/TvActivityTest.java \
-    $(BASE_DIR)/data/epg/EpgFetcherImplTest.java \
-    $(BASE_DIR)/guide/ProgramItemViewTest.java \
-    $(BASE_DIR)/guide/ProgramTableAdapterTest.java \
-
-LOCAL_ROBOTEST_FILES := $(call find-files-in-subdirs,$(LOCAL_PATH)/src,*Test.java,.)
-LOCAL_ROBOTEST_FILES := $(filter-out $(EXCLUDE_FILES),$(LOCAL_ROBOTEST_FILES))
-
-LOCAL_JAVA_LIBRARIES := \
-    Robolectric_all-target \
-    TvRoboTests \
-    mockito-robolectric-prebuilt \
-    robolectric_android-all-stub \
-    tv-lib-truth \
-    tv-test-common \
-    tv-test-common-robo \
-
-LOCAL_TEST_PACKAGE := LiveTv
-
-LOCAL_ROBOTEST_TIMEOUT := 36000
-
-include external/robolectric-shadows/run_robotests.mk
diff --git a/tests/robotests/README.md b/tests/robotests/README.md
deleted file mode 100644
index 8e4bcb5..0000000
--- a/tests/robotests/README.md
+++ /dev/null
@@ -1,5 +0,0 @@
-Unit test suite for Live Channels using Robolectric.
-
-```
-$ m -j96 RunTvRoboTests
-```
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/tv/MainActivityRoboTest.java b/tests/robotests/src/com/android/tv/MainActivityRoboTest.java
deleted file mode 100644
index be7ae06..0000000
--- a/tests/robotests/src/com/android/tv/MainActivityRoboTest.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (C) 2018 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 static com.google.common.truth.Truth.assertThat;
-
-import android.media.tv.TvTrackInfo;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-
-import com.android.tv.common.flags.impl.DefaultLegacyFlags;
-import com.android.tv.data.ProgramDataManager;
-import com.android.tv.data.StreamInfo;
-import com.android.tv.testing.TestSingletonApp;
-import com.android.tv.testing.constants.ConfigConstants;
-import com.android.tv.ui.TunableTvView;
-import com.android.tv.util.TvInputManagerHelper;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.Robolectric;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadow.api.Shadow;
-
-import java.util.Arrays;
-
-/** Tests for {@link TunableTvView} */
-@RunWith(RobolectricTestRunner.class)
-@Config(
-        sdk = ConfigConstants.SDK,
-        application = TestSingletonApp.class,
-        shadows = {ShadowTvView.class})
-public class MainActivityRoboTest {
-    private ShadowTvView mShadowTvView;
-    private FakeMainActivity mMainActivity;
-
-    @Before
-    public void setUp() {
-        mMainActivity = Robolectric.buildActivity(FakeMainActivity.class).create().get();
-        mShadowTvView = Shadow.extract(mMainActivity.getTvView().getTvView());
-        mShadowTvView.listener = mMainActivity.getListener();
-    }
-
-    @Test
-    public void testSelectAudioTrack_autoSelect() {
-        mShadowTvView.mAudioTrackCountChanged = false;
-        setTracks(
-                TvTrackInfo.TYPE_AUDIO,
-                buildTrackForTesting(TvTrackInfo.TYPE_AUDIO, "EN audio 1", "EN"),
-                buildTrackForTesting(TvTrackInfo.TYPE_AUDIO, "FR audio 1", "FR"));
-        mMainActivity.selectAudioTrack("FR audio 1");
-        assertThat(mMainActivity.getSelectedTrack(TvTrackInfo.TYPE_AUDIO)).isEqualTo("FR audio 1");
-
-        setTracks(
-                TvTrackInfo.TYPE_AUDIO,
-                buildTrackForTesting(TvTrackInfo.TYPE_AUDIO, "EN audio 2", "EN"),
-                buildTrackForTesting(TvTrackInfo.TYPE_AUDIO, "FR audio 2", "FR"),
-                buildTrackForTesting(TvTrackInfo.TYPE_AUDIO, "FR audio 3", "FR"));
-        mMainActivity.applyMultiAudio(null);
-        // FR audio 2 is selected according the previously selected track.
-        assertThat(mMainActivity.getSelectedTrack(TvTrackInfo.TYPE_AUDIO)).isEqualTo("FR audio 2");
-    }
-
-    @Test
-    public void testSelectAudioTrack_audioTrackCountChanged() {
-        mShadowTvView.mAudioTrackCountChanged = true;
-        setTracks(
-                TvTrackInfo.TYPE_AUDIO,
-                buildTrackForTesting(TvTrackInfo.TYPE_AUDIO, "EN audio 1", "EN"),
-                buildTrackForTesting(TvTrackInfo.TYPE_AUDIO, "FR audio 1", "FR"));
-        mMainActivity.selectAudioTrack("FR audio 1");
-        assertThat(mMainActivity.getSelectedTrack(TvTrackInfo.TYPE_AUDIO)).isEqualTo("FR audio 1");
-
-        setTracks(
-                TvTrackInfo.TYPE_AUDIO,
-                buildTrackForTesting(TvTrackInfo.TYPE_AUDIO, "EN audio 2", "EN"),
-                buildTrackForTesting(TvTrackInfo.TYPE_AUDIO, "FR audio 2", "FR"),
-                buildTrackForTesting(TvTrackInfo.TYPE_AUDIO, "FR audio 3", "FR"));
-        mMainActivity.selectAudioTrack("FR audio 3");
-        // FR audio 3 is selected even if the track info has been changed
-        assertThat(mMainActivity.getSelectedTrack(TvTrackInfo.TYPE_AUDIO)).isEqualTo("FR audio 3");
-    }
-
-    @Test
-    public void testSelectAudioTrack_audioTrackCountNotChanged() {
-        mShadowTvView.mAudioTrackCountChanged = false;
-        setTracks(
-                TvTrackInfo.TYPE_AUDIO,
-                buildTrackForTesting(TvTrackInfo.TYPE_AUDIO, "EN audio 1", "EN"),
-                buildTrackForTesting(TvTrackInfo.TYPE_AUDIO, "FR audio 1", "FR"));
-        mMainActivity.selectAudioTrack("FR audio 1");
-        assertThat(mMainActivity.getSelectedTrack(TvTrackInfo.TYPE_AUDIO)).isEqualTo("FR audio 1");
-
-        setTracks(
-                TvTrackInfo.TYPE_AUDIO,
-                buildTrackForTesting(TvTrackInfo.TYPE_AUDIO, "EN audio 2", "EN"),
-                buildTrackForTesting(TvTrackInfo.TYPE_AUDIO, "FR audio 2", "FR"),
-                buildTrackForTesting(TvTrackInfo.TYPE_AUDIO, "FR audio 3", "FR"));
-        mMainActivity.selectAudioTrack("FR audio 3");
-        assertThat(mMainActivity.getSelectedTrack(TvTrackInfo.TYPE_AUDIO)).isEqualTo("FR audio 3");
-    }
-
-    private void setTracks(int type, TvTrackInfo... tracks) {
-        mShadowTvView.mTracks.put(type, Arrays.asList(tracks));
-        mShadowTvView.mSelectedTracks.put(type, null);
-    }
-
-    private TvTrackInfo buildTrackForTesting(int type, String id, String language) {
-        return new TvTrackInfo.Builder(type, id)
-                .setLanguage(language)
-                .setAudioChannelCount(0)
-                .build();
-    }
-
-    /** A {@link MainActivity} class for tests */
-    public static class FakeMainActivity extends MainActivity {
-        private MyOnTuneListener mListener;
-
-        @Override
-        protected void onCreate(Bundle savedInstanceState) {
-            // Override onCreate() to omit unnecessary member variables
-            mTvView =
-                    (TunableTvView)
-                            LayoutInflater.from(RuntimeEnvironment.application)
-                                    .inflate(R.layout.activity_tv, null)
-                                    .findViewById(R.id.main_tunable_tv_view);
-            DefaultLegacyFlags legacyFlags = DefaultLegacyFlags.DEFAULT;
-            mTvView.initialize(
-                    new ProgramDataManager(RuntimeEnvironment.application),
-                    new TvInputManagerHelper(RuntimeEnvironment.application, legacyFlags),
-                    legacyFlags);
-            mTvView.start();
-            mListener =
-                    new MyOnTuneListener() {
-                        @Override
-                        public void onStreamInfoChanged(
-                                StreamInfo info, boolean allowAutoSelectionOfTrack) {
-                            applyMultiAudio(
-                                    allowAutoSelectionOfTrack
-                                            ? null
-                                            : getSelectedTrack(TvTrackInfo.TYPE_AUDIO));
-                        }
-                    };
-            mTvView.setOnTuneListener(mListener);
-        }
-
-        public TunableTvView getTvView() {
-            return mTvView;
-        }
-
-        public MyOnTuneListener getListener() {
-            return mListener;
-        }
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/MediaSessionWrapperTest.java b/tests/robotests/src/com/android/tv/MediaSessionWrapperTest.java
deleted file mode 100644
index 5be62ac..0000000
--- a/tests/robotests/src/com/android/tv/MediaSessionWrapperTest.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * 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 static com.google.common.truth.Truth.assertThat;
-
-import android.app.PendingIntent;
-import android.content.Intent;
-import android.media.MediaMetadata;
-import android.media.session.PlaybackState;
-
-import com.android.tv.testing.EpgTestData;
-import com.android.tv.testing.TvRobolectricTestRunner;
-import com.android.tv.testing.TestSingletonApp;
-import com.android.tv.testing.constants.ConfigConstants;
-import com.android.tv.testing.shadows.ShadowMediaSession;
-
-import com.google.common.collect.Maps;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadow.api.Shadow;
-
-import java.util.Map;
-
-/** Tests fpr {@link MediaSessionWrapper}. */
-@RunWith(TvRobolectricTestRunner.class)
-@Config(
-        sdk = ConfigConstants.SDK,
-        application = TestSingletonApp.class,
-        shadows = {ShadowMediaSession.class})
-public class MediaSessionWrapperTest {
-
-    private static final int TEST_REQUEST_CODE = 1337;
-
-    private ShadowMediaSession mediaSession;
-    private MediaSessionWrapper mediaSessionWrapper;
-    private PendingIntent pendingIntent;
-
-    @Before
-    public void setUp() {
-        pendingIntent =
-                PendingIntent.getActivity(
-                        RuntimeEnvironment.application, TEST_REQUEST_CODE, new Intent(), 0);
-        mediaSessionWrapper =
-                new MediaSessionWrapper(RuntimeEnvironment.application, pendingIntent) {
-                    @Override
-                    void initMediaController() {
-                        // Not use MediaController for tests here because:
-                        // 1. it's not allow to shadow MediaController
-                        // 2. The Context TestSingletonApp is not an instance of Activity so
-                        // Activity.setMediaController cannot be called.
-                        // onPlaybackStateChanged() is called in #setPlaybackState instead.
-                    }
-
-                    @Override
-                    void unregisterMediaControllerCallback() {}
-                };
-        mediaSession = Shadow.extract(mediaSessionWrapper.getMediaSession());
-    }
-
-    @Test
-    public void setSessionActivity() {
-        assertThat(mediaSession.mSessionActivity).isEqualTo(this.pendingIntent);
-    }
-
-    @Test
-    public void setPlaybackState_true() {
-        setPlaybackState(true);
-        assertThat(mediaSession.mActive).isTrue();
-        assertThat(mediaSession.mPlaybackState.getState()).isEqualTo(PlaybackState.STATE_PLAYING);
-    }
-
-    @Test
-    public void setPlaybackState_false() {
-        setPlaybackState(false);
-        assertThat(mediaSession.mActive).isFalse();
-        assertThat(mediaSession.mPlaybackState).isNull();
-    }
-
-    @Test
-    public void setPlaybackState_trueThenFalse() {
-        setPlaybackState(true);
-        setPlaybackState(false);
-        assertThat(mediaSession.mActive).isFalse();
-        assertThat(mediaSession.mPlaybackState.getState()).isEqualTo(PlaybackState.STATE_STOPPED);
-    }
-
-    @Test
-    public void update_channel10() {
-
-        mediaSessionWrapper.update(false, EpgTestData.toTvChannel(EpgTestData.CHANNEL_10), null);
-        assertThat(asMap(mediaSession.mMediaMetadata))
-                .containsExactly(MediaMetadata.METADATA_KEY_TITLE, "Channel TEN");
-    }
-
-    @Test
-    public void update_blockedChannel10() {
-        mediaSessionWrapper.update(true, EpgTestData.toTvChannel(EpgTestData.CHANNEL_10), null);
-        assertThat(asMap(mediaSession.mMediaMetadata))
-                .containsExactly(
-                        MediaMetadata.METADATA_KEY_TITLE,
-                        "Channel blocked",
-                        MediaMetadata.METADATA_KEY_ART,
-                        null);
-    }
-
-    @Test
-    public void update_channel10Program2() {
-        mediaSessionWrapper.update(
-                false, EpgTestData.toTvChannel(EpgTestData.CHANNEL_10), EpgTestData.PROGRAM_2);
-        assertThat(asMap(mediaSession.mMediaMetadata))
-                .containsExactly(MediaMetadata.METADATA_KEY_TITLE, "Program 2");
-    }
-
-    @Test
-    public void update_blockedChannel10Program2() {
-        mediaSessionWrapper.update(
-                true, EpgTestData.toTvChannel(EpgTestData.CHANNEL_10), EpgTestData.PROGRAM_2);
-        assertThat(asMap(mediaSession.mMediaMetadata))
-                .containsExactly(
-                        MediaMetadata.METADATA_KEY_TITLE,
-                        "Channel blocked",
-                        MediaMetadata.METADATA_KEY_ART,
-                        null);
-        // TODO(b/70559407): test async loading of images.
-    }
-
-    @Test
-    public void release() {
-        mediaSessionWrapper.release();
-        assertThat(mediaSession.mReleased).isTrue();
-    }
-
-    private Map<String, Object> asMap(MediaMetadata mediaMetadata) {
-        return Maps.asMap(mediaMetadata.keySet(), key -> mediaMetadata.getString(key));
-    }
-
-    private void setPlaybackState(boolean isPlaying) {
-        mediaSessionWrapper.setPlaybackState(isPlaying);
-        mediaSessionWrapper
-                .getMediaControllerCallback()
-                .onPlaybackStateChanged(
-                        isPlaying
-                                ? MediaSessionWrapper.MEDIA_SESSION_STATE_PLAYING
-                                : MediaSessionWrapper.MEDIA_SESSION_STATE_STOPPED);
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/SetupPassthroughActivityTest.java b/tests/robotests/src/com/android/tv/SetupPassthroughActivityTest.java
deleted file mode 100644
index 76037b4..0000000
--- a/tests/robotests/src/com/android/tv/SetupPassthroughActivityTest.java
+++ /dev/null
@@ -1,447 +0,0 @@
-/*
- * 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 static com.google.common.truth.Truth.assertThat;
-
-import static org.robolectric.Shadows.shadowOf;
-
-import android.app.Activity;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.ServiceInfo;
-import android.media.tv.TvInputInfo;
-import android.os.Build.VERSION;
-import android.os.Build.VERSION_CODES;
-import android.support.annotation.Nullable;
-
-import androidx.test.core.app.ApplicationProvider;
-
-import com.android.tv.common.CommonConstants;
-import com.android.tv.common.dagger.ApplicationModule;
-import com.android.tv.common.flags.impl.DefaultLegacyFlags;
-import com.android.tv.common.flags.impl.SettableFlagsModule;
-import com.android.tv.common.util.CommonUtils;
-import com.android.tv.data.ChannelDataManager;
-import com.android.tv.data.epg.EpgFetcher;
-import com.android.tv.features.TvFeatures;
-import com.android.tv.modules.TvSingletonsModule;
-import com.android.tv.testing.FakeTvInputManager;
-import com.android.tv.testing.FakeTvInputManagerHelper;
-import com.android.tv.testing.TestSingletonApp;
-import com.android.tv.testing.constants.ConfigConstants;
-import com.android.tv.tunerinputcontroller.BuiltInTunerManager;
-import com.android.tv.util.AsyncDbTask.DbExecutor;
-import com.android.tv.util.SetupUtils;
-import com.android.tv.util.TvInputManagerHelper;
-
-import com.google.android.tv.partner.support.EpgContract;
-import com.google.common.base.Optional;
-import com.android.tv.common.flags.proto.TypedFeatures.StringListParam;
-
-import dagger.Component;
-import dagger.Module;
-import dagger.Provides;
-import dagger.android.AndroidInjectionModule;
-import dagger.android.AndroidInjector;
-import dagger.android.DispatchingAndroidInjector;
-import dagger.android.HasAndroidInjector;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentMatchers;
-import org.mockito.Mockito;
-import org.robolectric.Robolectric;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.android.controller.ActivityController;
-import org.robolectric.android.util.concurrent.RoboExecutorService;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowActivity;
-
-import java.util.concurrent.Executor;
-
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-/** Tests for {@link SetupPassthroughActivity}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK, application = SetupPassthroughActivityTest.MyTestApp.class)
-public class SetupPassthroughActivityTest {
-
-    private static final int REQUEST_START_SETUP_ACTIVITY = 200;
-
-    private MyTestApp testSingletonApp;
-
-    private TvInputInfo testInput;
-
-    @Before
-    public void setup() {
-        testInput = createMockInput("com.example/.Input");
-        testSingletonApp = (MyTestApp) ApplicationProvider.getApplicationContext();
-        testSingletonApp.flagsModule.legacyFlags =
-                DefaultLegacyFlags.builder().enableQaFeatures(true).build();
-        testSingletonApp.tvInputManagerHelper.getFakeTvInputManager();
-    }
-
-    @After
-    public void after() {
-        TvFeatures.CLOUD_EPG_FOR_3RD_PARTY.resetForTests();
-    }
-
-    @Test
-    public void create_emptyIntent() {
-        SetupPassthroughActivity activity =
-                Robolectric.buildActivity(SetupPassthroughActivity.class, new Intent())
-                        .create()
-                        .get();
-        ShadowActivity.IntentForResult shadowIntent =
-                shadowOf(activity).getNextStartedActivityForResult();
-        // Since there is no inputs, the next activity should not be started.
-        assertThat(shadowIntent).isNull();
-        assertThat(activity.isFinishing()).isTrue();
-    }
-
-    @Test
-    public void create_noInputs() {
-        SetupPassthroughActivity activity = createSetupActivityFor("com.example/.Input");
-        ShadowActivity.IntentForResult shadowIntent =
-                shadowOf(activity).getNextStartedActivityForResult();
-        // Since there is no inputs, the next activity should not be started.
-        assertThat(shadowIntent).isNull();
-        assertThat(activity.isFinishing()).isTrue();
-    }
-
-    @Test
-    public void create_inputNotFound() {
-        testSingletonApp.tvInputManagerHelper = new FakeTvInputManagerHelper(testSingletonApp);
-        testSingletonApp.tvInputManagerHelper.start();
-        testSingletonApp.tvInputManagerHelper.getFakeTvInputManager().add(testInput, -1);
-        SetupPassthroughActivity activity = createSetupActivityFor("com.example/.Other");
-        ShadowActivity.IntentForResult shadowIntent =
-                shadowOf(activity).getNextStartedActivityForResult();
-        // Since the input is not found, the next activity should not be started.
-        assertThat(shadowIntent).isNull();
-        assertThat(activity.isFinishing()).isTrue();
-    }
-
-    @Test
-    public void create_validInput() {
-        testSingletonApp.tvInputManagerHelper.start();
-        testSingletonApp.tvInputManagerHelper.getFakeTvInputManager().add(testInput, -1);
-        SetupPassthroughActivity activity = createSetupActivityFor(testInput.getId());
-
-        ShadowActivity.IntentForResult shadowIntent =
-                shadowOf(activity).getNextStartedActivityForResult();
-        assertThat(shadowIntent).isNotNull();
-        assertThat(shadowIntent.options).isNull();
-        assertThat(shadowIntent.intent.getExtras()).isNotNull();
-        assertThat(shadowIntent.requestCode).isEqualTo(REQUEST_START_SETUP_ACTIVITY);
-        assertThat(activity.isFinishing()).isFalse();
-    }
-
-    @Test
-    public void create_trustedCallingPackage() {
-        testSingletonApp.tvInputManagerHelper.start();
-        testSingletonApp.tvInputManagerHelper.getFakeTvInputManager().add(testInput, -1);
-
-        ActivityController<SetupPassthroughActivity> activityController =
-                Robolectric.buildActivity(
-                        SetupPassthroughActivity.class,
-                        CommonUtils.createSetupIntent(new Intent(), testInput.getId()));
-        SetupPassthroughActivity activity = activityController.get();
-        ShadowActivity shadowActivity = shadowOf(activity);
-        shadowActivity.setCallingActivity(
-                new ComponentName(CommonConstants.BASE_PACKAGE, "com.example.MyClass"));
-        activityController.create();
-
-        ShadowActivity.IntentForResult shadowIntent =
-                shadowActivity.getNextStartedActivityForResult();
-        assertThat(shadowIntent).isNotNull();
-        assertThat(shadowIntent.options).isNull();
-        assertThat(shadowIntent.intent.getExtras()).isNotNull();
-        assertThat(shadowIntent.requestCode).isEqualTo(REQUEST_START_SETUP_ACTIVITY);
-        assertThat(activity.isFinishing()).isFalse();
-    }
-
-    @Test
-    public void create_nonTrustedCallingPackage() {
-        testSingletonApp.tvInputManagerHelper.start();
-        testSingletonApp.tvInputManagerHelper.getFakeTvInputManager().add(testInput, -1);
-
-        ActivityController<SetupPassthroughActivity> activityController =
-                Robolectric.buildActivity(
-                        SetupPassthroughActivity.class,
-                        CommonUtils.createSetupIntent(new Intent(), testInput.getId()));
-        SetupPassthroughActivity activity = activityController.get();
-        ShadowActivity shadowActivity = shadowOf(activity);
-        shadowActivity.setCallingActivity(
-                new ComponentName("com.notTrusted", "com.notTrusted.MyClass"));
-        activityController.create();
-
-        ShadowActivity.IntentForResult shadowIntent =
-                shadowActivity.getNextStartedActivityForResult();
-        // Since the calling activity is not trusted, the next activity should not be started.
-        assertThat(shadowIntent).isNull();
-        assertThat(activity.isFinishing()).isTrue();
-    }
-
-    @Test
-    public void onActivityResult_canceled() {
-        testSingletonApp.tvInputManagerHelper.getFakeTvInputManager().add(testInput, -1);
-        SetupPassthroughActivity activity = createSetupActivityFor(testInput.getId());
-
-        activity.onActivityResult(0, Activity.RESULT_CANCELED, null);
-        assertThat(activity.isFinishing()).isTrue();
-        assertThat(shadowOf(activity).getResultCode()).isEqualTo(Activity.RESULT_CANCELED);
-    }
-
-    @Test
-    public void onActivityResult_ok() {
-        TestSetupUtils setupUtils = new TestSetupUtils(RuntimeEnvironment.application);
-        testSingletonApp.setupUtils = setupUtils;
-        testSingletonApp.tvInputManagerHelper.getFakeTvInputManager().add(testInput, -1);
-        SetupPassthroughActivity activity = createSetupActivityFor(testInput.getId());
-        activity.onActivityResult(REQUEST_START_SETUP_ACTIVITY, Activity.RESULT_OK, null);
-
-        assertThat(testSingletonApp.epgFetcher.fetchStarted).isFalse();
-        assertThat(setupUtils.finishedId).isEqualTo("com.example/.Input");
-        assertThat(activity.isFinishing()).isFalse();
-
-        setupUtils.finishedRunnable.run();
-        assertThat(activity.isFinishing()).isTrue();
-        assertThat(shadowOf(activity).getResultCode()).isEqualTo(Activity.RESULT_OK);
-    }
-
-    @Test
-    public void onActivityResult_3rdPartyEpg_ok() {
-        TvFeatures.CLOUD_EPG_FOR_3RD_PARTY.enableForTest();
-        TestSetupUtils setupUtils = new TestSetupUtils(RuntimeEnvironment.application);
-        testSingletonApp.setupUtils = setupUtils;
-        testSingletonApp.tvInputManagerHelper.getFakeTvInputManager().add(testInput, -1);
-        testSingletonApp.getCloudEpgFlags().setThirdPartyEpgInputCsv(testInput.getId());
-        SetupPassthroughActivity activity = createSetupActivityFor(testInput.getId());
-        Intent data = new Intent();
-        data.putExtra(EpgContract.EXTRA_USE_CLOUD_EPG, true);
-        data.putExtra(TvInputInfo.EXTRA_INPUT_ID, testInput.getId());
-        activity.onActivityResult(REQUEST_START_SETUP_ACTIVITY, Activity.RESULT_OK, data);
-
-        assertThat(testSingletonApp.epgFetcher.fetchStarted).isTrue();
-        assertThat(setupUtils.finishedId).isEqualTo("com.example/.Input");
-        assertThat(activity.isFinishing()).isFalse();
-
-        setupUtils.finishedRunnable.run();
-        assertThat(activity.isFinishing()).isTrue();
-        assertThat(shadowOf(activity).getResultCode()).isEqualTo(Activity.RESULT_OK);
-    }
-
-    @Test
-    public void onActivityResult_3rdPartyEpg_notWhiteListed() {
-        TvFeatures.CLOUD_EPG_FOR_3RD_PARTY.enableForTest();
-        TestSetupUtils setupUtils = new TestSetupUtils(RuntimeEnvironment.application);
-        testSingletonApp.setupUtils = setupUtils;
-        testSingletonApp.tvInputManagerHelper.getFakeTvInputManager().add(testInput, -1);
-        SetupPassthroughActivity activity = createSetupActivityFor(testInput.getId());
-        Intent data = new Intent();
-        data.putExtra(EpgContract.EXTRA_USE_CLOUD_EPG, true);
-        data.putExtra(TvInputInfo.EXTRA_INPUT_ID, testInput.getId());
-        activity.onActivityResult(REQUEST_START_SETUP_ACTIVITY, Activity.RESULT_OK, data);
-
-        assertThat(testSingletonApp.epgFetcher.fetchStarted).isFalse();
-        assertThat(setupUtils.finishedId).isEqualTo("com.example/.Input");
-        assertThat(activity.isFinishing()).isFalse();
-
-        setupUtils.finishedRunnable.run();
-        assertThat(activity.isFinishing()).isTrue();
-        assertThat(shadowOf(activity).getResultCode()).isEqualTo(Activity.RESULT_OK);
-    }
-
-    @Test
-    public void onActivityResult_3rdPartyEpg_disabled() {
-        TvFeatures.CLOUD_EPG_FOR_3RD_PARTY.disableForTests();
-        TestSetupUtils setupUtils = new TestSetupUtils(RuntimeEnvironment.application);
-        testSingletonApp.setupUtils = setupUtils;
-        testSingletonApp.tvInputManagerHelper.getFakeTvInputManager().add(testInput, -1);
-        testSingletonApp.getCloudEpgFlags().setThirdPartyEpgInputCsv(testInput.getId());
-        testSingletonApp.dbExecutor = new RoboExecutorService();
-        SetupPassthroughActivity activity = createSetupActivityFor(testInput.getId());
-        Intent data = new Intent();
-        data.putExtra(EpgContract.EXTRA_USE_CLOUD_EPG, true);
-        data.putExtra(TvInputInfo.EXTRA_INPUT_ID, testInput.getId());
-        activity.onActivityResult(REQUEST_START_SETUP_ACTIVITY, Activity.RESULT_OK, data);
-
-        assertThat(testSingletonApp.epgFetcher.fetchStarted).isFalse();
-        assertThat(setupUtils.finishedId).isEqualTo("com.example/.Input");
-        assertThat(activity.isFinishing()).isFalse();
-
-        setupUtils.finishedRunnable.run();
-        assertThat(activity.isFinishing()).isTrue();
-        assertThat(shadowOf(activity).getResultCode()).isEqualTo(Activity.RESULT_OK);
-    }
-
-    @Test
-    public void onActivityResult_ok_tvInputInfo_null() {
-        TestSetupUtils setupUtils = new TestSetupUtils(RuntimeEnvironment.application);
-        testSingletonApp.setupUtils = setupUtils;
-        FakeTvInputManager tvInputManager =
-                testSingletonApp.tvInputManagerHelper.getFakeTvInputManager();
-        SetupPassthroughActivity activity = createSetupActivityFor(testInput.getId());
-        activity.onActivityResult(REQUEST_START_SETUP_ACTIVITY, Activity.RESULT_OK, null);
-
-        assertThat(tvInputManager.getTvInputInfo(testInput.getId())).isEqualTo(null);
-        assertThat(testSingletonApp.epgFetcher.fetchStarted).isFalse();
-        assertThat(activity.isFinishing()).isTrue();
-
-        assertThat(shadowOf(activity).getResultCode()).isEqualTo(Activity.RESULT_OK);
-    }
-
-    private SetupPassthroughActivity createSetupActivityFor(String inputId) {
-        return Robolectric.buildActivity(
-                        SetupPassthroughActivity.class,
-                        CommonUtils.createSetupIntent(new Intent(), inputId))
-                .create()
-                .get();
-    }
-
-    private TvInputInfo createMockInput(String inputId) {
-        TvInputInfo tvInputInfo = Mockito.mock(TvInputInfo.class);
-        ServiceInfo serviceInfo = new ServiceInfo();
-        ApplicationInfo applicationInfo = new ApplicationInfo();
-        Mockito.when(tvInputInfo.getId()).thenReturn(inputId);
-        serviceInfo.packageName = inputId.substring(0, inputId.indexOf('/'));
-        serviceInfo.applicationInfo = applicationInfo;
-        applicationInfo.flags = 0;
-        Mockito.when(tvInputInfo.getServiceInfo()).thenReturn(serviceInfo);
-        Mockito.when(tvInputInfo.loadLabel(ArgumentMatchers.any())).thenReturn("testLabel");
-        if (VERSION.SDK_INT >= VERSION_CODES.N) {
-            Mockito.when(tvInputInfo.loadCustomLabel(ArgumentMatchers.any()))
-                    .thenReturn("testCustomLabel");
-        }
-        return tvInputInfo;
-    }
-
-    /**
-     * Test SetupUtils.
-     *
-     * <p>SetupUtils has lots of DB and threading interactions, that make it hard to test. This
-     * bypasses all of that.
-     */
-    private static class TestSetupUtils extends SetupUtils {
-        public String finishedId;
-        public Runnable finishedRunnable;
-
-        private TestSetupUtils(Context context) {
-            super(context, Optional.absent());
-        }
-
-        @Override
-        public void onTvInputSetupFinished(String inputId, @Nullable Runnable postRunnable) {
-            finishedId = inputId;
-            finishedRunnable = postRunnable;
-        }
-    }
-
-    /** Test app for {@link SetupPassthroughActivityTest} */
-    public static class MyTestApp extends TestSingletonApp implements HasAndroidInjector {
-
-        @Inject DispatchingAndroidInjector<Object> dispatchingAndroidInjector;
-
-        @Override
-        public void onCreate() {
-
-            super.onCreate();
-            // Inject afterwards so we can use objects created in super.
-            // Note TestSingletonApp does not do injection so it is safe
-            applicationInjector().inject(this);
-        }
-
-        @Override
-        public AndroidInjector<Object> androidInjector() {
-            return dispatchingAndroidInjector;
-        }
-
-        protected AndroidInjector<MyTestApp> applicationInjector() {
-
-            return DaggerSetupPassthroughActivityTest_TestComponent.builder()
-                    .applicationModule(new ApplicationModule(this))
-                    .tvSingletonsModule(new TvSingletonsModule(this))
-                    .testModule(new TestModule(this))
-                    .settableFlagsModule(flagsModule)
-                    .build();
-        }
-    }
-
-    /** Dagger component for {@link SetupPassthroughActivityTest}. */
-    @Singleton
-    @Component(
-            modules = {
-                AndroidInjectionModule.class,
-                TestModule.class,
-            })
-    interface TestComponent extends AndroidInjector<MyTestApp> {}
-
-    @Module(
-            includes = {
-                SetupPassthroughActivity.Module.class,
-                ApplicationModule.class,
-                TvSingletonsModule.class,
-                SettableFlagsModule.class,
-            })
-    /** Module for {@link MyTestApp} */
-    static class TestModule {
-        private final MyTestApp myTestApp;
-
-        TestModule(MyTestApp test) {
-            myTestApp = test;
-        }
-
-        @Provides
-        Optional<BuiltInTunerManager> providesBuiltInTunerManager() {
-            return Optional.absent();
-        }
-
-        @Provides
-        TvInputManagerHelper providesTvInputManagerHelper() {
-            return myTestApp.tvInputManagerHelper;
-        }
-
-        @Provides
-        SetupUtils providesTestSetupUtils() {
-            return myTestApp.setupUtils;
-        }
-
-        @Provides
-        @DbExecutor
-        Executor providesDbExecutor() {
-            return myTestApp.dbExecutor;
-        }
-
-        @Provides
-        ChannelDataManager providesChannelDataManager() {
-            return myTestApp.getChannelDataManager();
-        }
-
-        @Provides
-        EpgFetcher providesEpgFetcher() {
-            return myTestApp.epgFetcher;
-        }
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/ShadowTvView.java b/tests/robotests/src/com/android/tv/ShadowTvView.java
deleted file mode 100644
index 8aad9f0..0000000
--- a/tests/robotests/src/com/android/tv/ShadowTvView.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2018 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.media.tv.TvTrackInfo;
-import android.media.tv.TvView;
-import android.util.AttributeSet;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-import org.robolectric.shadows.ShadowView;
-
-// TODO(b/78304522): move this class to robolectric
-/** Shadow class of {@link TvView}. */
-@Implements(TvView.class)
-public class ShadowTvView extends ShadowView {
-    public Map<Integer, String> mSelectedTracks = new HashMap<>();
-    public Map<Integer, List<TvTrackInfo>> mTracks = new HashMap<>();
-    public MainActivity.MyOnTuneListener listener;
-    public TvView.TvInputCallback mCallback;
-    public boolean mAudioTrackCountChanged;
-
-    @Implementation
-    public void __constructor__(Context context) {
-    }
-
-    @Implementation
-    public void __constructor__(Context context, AttributeSet attrs) {
-    }
-
-    @Override
-    public void __constructor__(Context context, AttributeSet attrs, int defStyleAttr) {
-    }
-
-    @Implementation
-    public List<TvTrackInfo> getTracks(int type) {
-        return mTracks.get(type);
-    }
-
-    @Implementation
-    public void selectTrack(int type, String trackId) {
-        mSelectedTracks.put(type, trackId);
-        int infoIndex = findTrackIndex(type, trackId);
-        // for some drivers, audio track count is set to 0 until the corresponding track is
-        // selected. Here we replace the track with another one whose audio track count is non-zero
-        // to test this case.
-        if (mAudioTrackCountChanged) {
-            replaceTrack(type, infoIndex);
-        }
-        mCallback.onTrackSelected("fakeInputId", type, trackId);
-    }
-
-    @Implementation
-    public String getSelectedTrack(int type) {
-        return mSelectedTracks.get(type);
-    }
-
-    @Implementation
-    public void setCallback(TvView.TvInputCallback callback) {
-        mCallback = callback;
-    }
-
-    private int findTrackIndex(int type, String trackId) {
-        List<TvTrackInfo> tracks = mTracks.get(type);
-        if (tracks == null) {
-            return -1;
-        }
-        for (int i = 0; i < tracks.size(); i++) {
-            TvTrackInfo info = tracks.get(i);
-            if (info.getId().equals(trackId)) {
-                return i;
-            }
-        }
-        return -1;
-    }
-
-    private void replaceTrack(int type, int trackIndex) {
-        if (trackIndex >= 0) {
-            TvTrackInfo info = mTracks.get(type).get(trackIndex);
-            info = new TvTrackInfo
-                    .Builder(info.getType(), info.getId())
-                    .setLanguage(info.getLanguage())
-                    .setAudioChannelCount(info.getAudioChannelCount() + 2)
-                    .build();
-            mTracks.get(type).set(trackIndex, info);
-        }
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/TvActivityTest.java b/tests/robotests/src/com/android/tv/TvActivityTest.java
deleted file mode 100644
index c153de8..0000000
--- a/tests/robotests/src/com/android/tv/TvActivityTest.java
+++ /dev/null
@@ -1,48 +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;
-
-import android.content.Intent;
-
-import com.android.tv.testing.constants.ConfigConstants;
-import com.android.tv.util.Utils;
-
-import com.google.android.libraries.testing.truth.IntentSubject;
-import com.google.common.truth.Truth;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.Robolectric;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowApplication;
-
-/** Test for {@link TvActivity}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-public class TvActivityTest {
-
-    @Test
-    public void testLifeCycle() {
-        TvActivity activity = Robolectric.setupActivity(TvActivity.class);
-        Truth.assertThat(activity.isFinishing()).isTrue();
-
-        Intent nextStartedActivity = ShadowApplication.getInstance().getNextStartedActivity();
-        IntentSubject.assertThat(nextStartedActivity).hasComponentClass(MainActivity.class);
-        IntentSubject.assertThat(nextStartedActivity).hasExtra(Utils.EXTRA_KEY_FROM_LAUNCHER, true);
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/audio/AudioManagerHelperTest.java b/tests/robotests/src/com/android/tv/audio/AudioManagerHelperTest.java
deleted file mode 100644
index e71b562..0000000
--- a/tests/robotests/src/com/android/tv/audio/AudioManagerHelperTest.java
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * Copyright (C) 2018 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.audio;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.app.Activity;
-import android.media.AudioManager;
-import android.os.Build;
-
-import com.android.tv.testing.constants.ConfigConstants;
-import com.android.tv.ui.api.TunableTvViewPlayingApi;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.Robolectric;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.Shadows;
-import org.robolectric.annotation.Config;
-
-/** Tests for {@link AudioManagerHelper}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-public class AudioManagerHelperTest {
-
-    private AudioManagerHelper mAudioManagerHelper;
-    private TestTvView mTvView;
-    private AudioManager mAudioManager;
-
-    @Before
-    public void setup() {
-        Activity testActivity = Robolectric.buildActivity(Activity.class).get();
-        mTvView = new TestTvView();
-        mAudioManager = RuntimeEnvironment.application.getSystemService(AudioManager.class);
-
-        mAudioManagerHelper = new AudioManagerHelper(testActivity, mTvView);
-    }
-
-    @Test
-    public void onAudioFocusChange_none_noTimeShift() {
-        mTvView.mTimeShiftAvailable = false;
-
-        mAudioManagerHelper.onAudioFocusChange(AudioManager.AUDIOFOCUS_NONE);
-
-        assertThat(mTvView.mPaused).isNull();
-        assertThat(mTvView.mVolume).isZero();
-    }
-
-    @Test
-    public void onAudioFocusChange_none_TimeShift() {
-        mTvView.mTimeShiftAvailable = true;
-
-        mAudioManagerHelper.onAudioFocusChange(AudioManager.AUDIOFOCUS_NONE);
-
-        assertThat(mTvView.mPaused).isTrue();
-        assertThat(mTvView.mVolume).isNull();
-    }
-
-    @Test
-    public void onAudioFocusChange_gain_noTimeShift() {
-        mTvView.mTimeShiftAvailable = false;
-
-        mAudioManagerHelper.onAudioFocusChange(AudioManager.AUDIOFOCUS_GAIN);
-
-        assertThat(mTvView.mPaused).isNull();
-        assertThat(mTvView.mVolume).isEqualTo(1.0f);
-    }
-
-    @Test
-    public void onAudioFocusChange_gain_timeShift() {
-        mTvView.mTimeShiftAvailable = true;
-
-        mAudioManagerHelper.onAudioFocusChange(AudioManager.AUDIOFOCUS_GAIN);
-
-        assertThat(mTvView.mPaused).isFalse();
-        assertThat(mTvView.mVolume).isNull();
-    }
-
-    @Test
-    public void onAudioFocusChange_loss_noTimeShift() {
-        mTvView.mTimeShiftAvailable = false;
-
-        mAudioManagerHelper.onAudioFocusChange(AudioManager.AUDIOFOCUS_LOSS);
-
-        assertThat(mTvView.mPaused).isNull();
-        assertThat(mTvView.mVolume).isEqualTo(0.0f);
-    }
-
-    @Test
-    public void onAudioFocusChange_loss_timeShift() {
-        mTvView.mTimeShiftAvailable = true;
-
-        mAudioManagerHelper.onAudioFocusChange(AudioManager.AUDIOFOCUS_LOSS);
-
-        assertThat(mTvView.mPaused).isTrue();
-        assertThat(mTvView.mVolume).isNull();
-    }
-
-    @Test
-    public void onAudioFocusChange_lossTransient_noTimeShift() {
-        mTvView.mTimeShiftAvailable = false;
-
-        mAudioManagerHelper.onAudioFocusChange(AudioManager.AUDIOFOCUS_LOSS_TRANSIENT);
-
-        assertThat(mTvView.mPaused).isNull();
-        assertThat(mTvView.mVolume).isEqualTo(0.0f);
-    }
-
-    @Test
-    public void onAudioFocusChange_lossTransient_timeShift() {
-        mTvView.mTimeShiftAvailable = true;
-
-        mAudioManagerHelper.onAudioFocusChange(AudioManager.AUDIOFOCUS_LOSS_TRANSIENT);
-
-        assertThat(mTvView.mPaused).isTrue();
-        assertThat(mTvView.mVolume).isNull();
-    }
-
-    @Test
-    public void onAudioFocusChange_lossTransientCanDuck_noTimeShift() {
-        mTvView.mTimeShiftAvailable = false;
-
-        mAudioManagerHelper.onAudioFocusChange(AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK);
-
-        assertThat(mTvView.mPaused).isNull();
-        assertThat(mTvView.mVolume).isEqualTo(0.3f);
-    }
-
-    @Test
-    public void onAudioFocusChange_lossTransientCanDuck_timeShift() {
-        mTvView.mTimeShiftAvailable = true;
-
-        mAudioManagerHelper.onAudioFocusChange(AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK);
-
-        assertThat(mTvView.mPaused).isTrue();
-        assertThat(mTvView.mVolume).isNull();
-    }
-
-    @Test
-    @Config(sdk = {ConfigConstants.SDK, Build.VERSION_CODES.O})
-    public void requestAudioFocus_granted() {
-        Shadows.shadowOf(mAudioManager)
-                .setNextFocusRequestResponse(AudioManager.AUDIOFOCUS_REQUEST_GRANTED);
-        mAudioManagerHelper.requestAudioFocus();
-
-        assertThat(mTvView.mPaused).isNull();
-        assertThat(mTvView.mVolume).isEqualTo(1.0f);
-    }
-
-    @Test
-    @Config(sdk = {ConfigConstants.SDK, Build.VERSION_CODES.O})
-    public void requestAudioFocus_failed() {
-        Shadows.shadowOf(mAudioManager)
-                .setNextFocusRequestResponse(AudioManager.AUDIOFOCUS_REQUEST_FAILED);
-
-        mAudioManagerHelper.requestAudioFocus();
-
-        assertThat(mTvView.mPaused).isNull();
-        assertThat(mTvView.mVolume).isZero();
-    }
-
-    @Test
-    @Config(sdk = {ConfigConstants.SDK, Build.VERSION_CODES.O})
-    public void requestAudioFocus_delayed() {
-        Shadows.shadowOf(mAudioManager)
-                .setNextFocusRequestResponse(AudioManager.AUDIOFOCUS_REQUEST_DELAYED);
-
-        mAudioManagerHelper.requestAudioFocus();
-
-        assertThat(mTvView.mPaused).isNull();
-        assertThat(mTvView.mVolume).isZero();
-    }
-
-    @Test
-    public void setVolumeByAudioFocusStatus_started() {
-        mAudioManagerHelper.setVolumeByAudioFocusStatus();
-
-        assertThat(mTvView.mPaused).isNull();
-        assertThat(mTvView.mVolume).isZero();
-    }
-
-    @Test
-    public void setVolumeByAudioFocusStatus_notStarted() {
-        mTvView.mStarted = false;
-        mAudioManagerHelper.setVolumeByAudioFocusStatus();
-
-        assertThat(mTvView.mPaused).isNull();
-        assertThat(mTvView.mVolume).isNull();
-    }
-
-    private static class TestTvView implements TunableTvViewPlayingApi {
-        private boolean mStarted = true;
-        private boolean mTimeShiftAvailable = false;
-        private Float mVolume = null;
-        private Boolean mPaused = null;
-
-        @Override
-        public boolean isPlaying() {
-            return mStarted;
-        }
-
-        @Override
-        public void setStreamVolume(float volume) {
-            mVolume = volume;
-        }
-
-        @Override
-        public void setTimeShiftListener(TimeShiftListener listener) {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public boolean isTimeShiftAvailable() {
-            return mTimeShiftAvailable;
-        }
-
-        @Override
-        public void timeShiftPlay() {
-            mPaused = false;
-        }
-
-        @Override
-        public void timeShiftPause() {
-            mPaused = true;
-        }
-
-        @Override
-        public void timeShiftRewind(int speed) {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public void timeShiftFastForward(int speed) {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public void timeShiftSeekTo(long timeMs) {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public long timeShiftGetCurrentPositionMs() {
-            throw new UnsupportedOperationException();
-        }
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/data/ChannelNumberTest.java b/tests/robotests/src/com/android/tv/data/ChannelNumberTest.java
deleted file mode 100644
index de051cf..0000000
--- a/tests/robotests/src/com/android/tv/data/ChannelNumberTest.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * 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 static com.android.tv.data.ChannelNumber.parseChannelNumber;
-import static com.android.tv.testing.ChannelNumberSubject.assertThat;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import com.android.tv.testing.ComparableTester;
-import com.android.tv.testing.constants.ConfigConstants;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-/** Tests for {@link ChannelNumber}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-public class ChannelNumberTest {
-
-    @Test
-    public void newChannelNumber() {
-        assertThat(new ChannelNumber()).isEmpty();
-    }
-
-    @Test
-    public void parseChannelNumber_empty() {
-        assertThat(parseChannelNumber("")).isNull();
-    }
-
-    @Test
-    public void parseChannelNumber_dash() {
-        assertThat(parseChannelNumber("-")).isNull();
-    }
-
-    @Test
-    public void parseChannelNumber_abcd12() {
-        assertThat(parseChannelNumber("abcd12")).isNull();
-    }
-
-    @Test
-    public void parseChannelNumber_12abcd() {
-        assertThat(parseChannelNumber("12abcd")).isNull();
-    }
-
-    @Test
-    public void parseChannelNumber_dash12() {
-        assertThat(parseChannelNumber("-12")).isNull();
-    }
-
-    @Test
-    public void parseChannelNumber_1() {
-        assertThat(parseChannelNumber("1")).displaysAs(1);
-    }
-
-    @Test
-    public void parseChannelNumber_1234dash4321() {
-        assertThat(parseChannelNumber("1234-4321")).displaysAs(1234, 4321);
-    }
-
-    @Test
-    public void parseChannelNumber_3dash4() {
-        assertThat(parseChannelNumber("3-4")).displaysAs(3, 4);
-    }
-
-    @Test
-    public void parseChannelNumber_5dash6() {
-        assertThat(parseChannelNumber("5-6")).displaysAs(5, 6);
-    }
-
-    @Test
-    public void compareTo() {
-        new ComparableTester<ChannelNumber>()
-                .addEquivalentGroup(parseChannelNumber("1"), parseChannelNumber("1"))
-                .addEquivalentGroup(parseChannelNumber("2"))
-                .addEquivalentGroup(parseChannelNumber("2-1"))
-                .addEquivalentGroup(parseChannelNumber("2-2"))
-                .addEquivalentGroup(parseChannelNumber("2-10"))
-                .addEquivalentGroup(parseChannelNumber("3"))
-                .addEquivalentGroup(parseChannelNumber("4"), parseChannelNumber("4-0"))
-                .addEquivalentGroup(parseChannelNumber("10"))
-                .addEquivalentGroup(parseChannelNumber("100"))
-                .test();
-    }
-
-    @Test
-    public void compare_null_null() {
-        assertThat(ChannelNumber.compare(null, null)).isEqualTo(0);
-    }
-
-    @Test
-    public void compare_1_1() {
-        assertThat(ChannelNumber.compare("1", "1")).isEqualTo(0);
-        ;
-    }
-
-    @Test
-    public void compare_null_1() {
-        assertThat(ChannelNumber.compare(null, "1")).isLessThan(0);
-    }
-
-    @Test
-    public void compare_abcd_1() {
-        assertThat(ChannelNumber.compare("abcd", "1")).isLessThan(0);
-    }
-
-    @Test
-    public void compare_dash1_1() {
-        assertThat(ChannelNumber.compare(".4", "1")).isLessThan(0);
-    }
-
-    @Test
-    public void compare_1_null() {
-        assertThat(ChannelNumber.compare("1", null)).isGreaterThan(0);
-    }
-
-    @Test
-    public void equivalent_null_to_null() {
-        assertThat(ChannelNumber.equivalent(null, null)).isTrue();
-    }
-
-    @Test
-    public void equivalent_1_to_1() {
-        assertThat(ChannelNumber.equivalent("1", "1")).isTrue();
-    }
-
-    @Test
-    public void equivalent_1d2_to_1() {
-        assertThat(ChannelNumber.equivalent("1-2", "1")).isTrue();
-    }
-
-    @Test
-    public void equivalent_1_to_1d2() {
-        assertThat(ChannelNumber.equivalent("1", "1-2")).isTrue();
-    }
-
-    @Test
-    public void equivalent_1_to_2_isFalse() {
-        assertThat(ChannelNumber.equivalent("1", "2")).isFalse();
-    }
-
-    @Test
-    public void equivalent_1d1_to_1d1() {
-        assertThat(ChannelNumber.equivalent("1-1", "1-1")).isTrue();
-    }
-
-    @Test
-    public void equivalent_1d1_to_1d2_isFalse() {
-        assertThat(ChannelNumber.equivalent("1-1", "1-2")).isFalse();
-    }
-
-    @Test
-    public void equivalent_1_to_null_isFalse() {
-        assertThat(ChannelNumber.equivalent("1", null)).isFalse();
-    }
-
-    @Test
-    public void equivalent_null_to_1_isFalse() {
-        assertThat(ChannelNumber.equivalent(null, "1")).isFalse();
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/data/GenreItemTest.java b/tests/robotests/src/com/android/tv/data/GenreItemTest.java
deleted file mode 100644
index b19dc0d..0000000
--- a/tests/robotests/src/com/android/tv/data/GenreItemTest.java
+++ /dev/null
@@ -1,95 +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.data;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.media.tv.TvContract.Programs.Genres;
-import android.os.Build;
-
-import com.android.tv.testing.TvRobolectricTestRunner;
-import com.android.tv.testing.constants.ConfigConstants;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-/** Tests for {@link GenreItems}. */
-@RunWith(TvRobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-public class GenreItemTest {
-    private static final String INVALID_GENRE = "INVALID GENRE";
-
-    @Test
-    public void testGetLabels() {
-        // Checks if no exception is thrown.
-        GenreItems.getLabels(RuntimeEnvironment.application);
-    }
-
-    @Test
-    public void testGetCanonicalGenre() {
-        int count = GenreItems.getGenreCount();
-        assertThat(GenreItems.getCanonicalGenre(GenreItems.ID_ALL_CHANNELS)).isNull();
-        for (int i = 1; i < count; ++i) {
-            assertThat(GenreItems.getCanonicalGenre(i)).isNotNull();
-        }
-    }
-
-    @Test
-    public void testGetId_base() {
-        int count = GenreItems.getGenreCount();
-        assertThat(GenreItems.getId(null)).isEqualTo(GenreItems.ID_ALL_CHANNELS);
-        assertThat(GenreItems.getId(INVALID_GENRE)).isEqualTo(GenreItems.ID_ALL_CHANNELS);
-        assertInRange(GenreItems.getId(Genres.FAMILY_KIDS), 1, count - 1);
-        assertInRange(GenreItems.getId(Genres.SPORTS), 1, count - 1);
-        assertInRange(GenreItems.getId(Genres.SHOPPING), 1, count - 1);
-        assertInRange(GenreItems.getId(Genres.MOVIES), 1, count - 1);
-        assertInRange(GenreItems.getId(Genres.COMEDY), 1, count - 1);
-        assertInRange(GenreItems.getId(Genres.TRAVEL), 1, count - 1);
-        assertInRange(GenreItems.getId(Genres.DRAMA), 1, count - 1);
-        assertInRange(GenreItems.getId(Genres.EDUCATION), 1, count - 1);
-        assertInRange(GenreItems.getId(Genres.ANIMAL_WILDLIFE), 1, count - 1);
-        assertInRange(GenreItems.getId(Genres.NEWS), 1, count - 1);
-        assertInRange(GenreItems.getId(Genres.GAMING), 1, count - 1);
-    }
-
-    @Test
-    public void testGetId_lmp_mr1() {
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {
-            assertThat(GenreItems.getId(Genres.ARTS)).isEqualTo(GenreItems.ID_ALL_CHANNELS);
-            assertThat(GenreItems.getId(Genres.ENTERTAINMENT))
-                    .isEqualTo(GenreItems.ID_ALL_CHANNELS);
-            assertThat(GenreItems.getId(Genres.LIFE_STYLE)).isEqualTo(GenreItems.ID_ALL_CHANNELS);
-            assertThat(GenreItems.getId(Genres.MUSIC)).isEqualTo(GenreItems.ID_ALL_CHANNELS);
-            assertThat(GenreItems.getId(Genres.PREMIER)).isEqualTo(GenreItems.ID_ALL_CHANNELS);
-            assertThat(GenreItems.getId(Genres.TECH_SCIENCE)).isEqualTo(GenreItems.ID_ALL_CHANNELS);
-        } else {
-            int count = GenreItems.getGenreCount();
-            assertInRange(GenreItems.getId(Genres.ARTS), 1, count - 1);
-            assertInRange(GenreItems.getId(Genres.ENTERTAINMENT), 1, count - 1);
-            assertInRange(GenreItems.getId(Genres.LIFE_STYLE), 1, count - 1);
-            assertInRange(GenreItems.getId(Genres.MUSIC), 1, count - 1);
-            assertInRange(GenreItems.getId(Genres.PREMIER), 1, count - 1);
-            assertInRange(GenreItems.getId(Genres.TECH_SCIENCE), 1, count - 1);
-        }
-    }
-
-    private void assertInRange(int value, int lower, int upper) {
-        assertThat(value >= lower && value <= upper).isTrue();
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/data/PreviewDataManagerTest.java b/tests/robotests/src/com/android/tv/data/PreviewDataManagerTest.java
deleted file mode 100644
index b341abf..0000000
--- a/tests/robotests/src/com/android/tv/data/PreviewDataManagerTest.java
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * 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 static com.google.common.truth.Truth.assertThat;
-
-import android.content.ContentProvider;
-import android.content.ContentValues;
-import android.content.pm.ProviderInfo;
-import android.database.Cursor;
-import android.database.SQLException;
-import android.net.Uri;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.util.Log;
-import android.util.Pair;
-
-import androidx.tvprovider.media.tv.PreviewProgram;
-import androidx.tvprovider.media.tv.TvContractCompat;
-
-import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
-import com.android.tv.dvr.data.RecordedProgram;
-import com.android.tv.testing.TvRobolectricTestRunner;
-import com.android.tv.testing.constants.ConfigConstants;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.Robolectric;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowContentResolver;
-import org.robolectric.shadows.ShadowLog;
-
-import java.util.List;
-
-/** Tests for {@link PreviewDataManager}. */
-@RunWith(TvRobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-public class PreviewDataManagerTest {
-    private static final long FAKE_PREVIEW_CHANNEL_ID = 2002;
-    private static final long FAKE_PROGRAM_ID = 1001;
-    private static final String FAKE_PROGRAM_TITLE = "test program";
-    private static final String FAKE_PROGRAM_POSTER_URI = "http://fake.uri/poster.jpg";
-    private static final long FAKE_CHANNEL_ID = 1002;
-    private static final String FAKE_CHANNEL_DISPLAY_NAME = "test channel";
-    private static final String FAKE_INPUT_ID = "test input";
-
-    private static class QueryExceptionProvider extends ContentProvider {
-        @Override
-        public boolean onCreate() {
-            return false;
-        }
-
-        @Nullable
-        @Override
-        public Cursor query(
-                @NonNull Uri uri,
-                @Nullable String[] projection,
-                @Nullable String selection,
-                @Nullable String[] selectionArgs,
-                @Nullable String sortOrder) {
-            throw new SQLException("Testing " + uri);
-        }
-
-        @Nullable
-        @Override
-        public String getType(@NonNull Uri uri) {
-            return null;
-        }
-
-        @Nullable
-        @Override
-        public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
-            return null;
-        }
-
-        @Override
-        public int delete(
-                @NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
-            return 0;
-        }
-
-        @Override
-        public int update(
-                @NonNull Uri uri,
-                @Nullable ContentValues values,
-                @Nullable String selection,
-                @Nullable String[] selectionArgs) {
-            return 0;
-        }
-    }
-
-    @Test
-    public void start() {
-        PreviewDataManager previewDataManager =
-                new PreviewDataManager(RuntimeEnvironment.application);
-        assertThat(previewDataManager.isLoadFinished()).isFalse();
-        previewDataManager.start();
-        assertThat(previewDataManager.isLoadFinished()).isTrue();
-    }
-
-    @Test
-    public void queryPreviewData_sqlexception() {
-        ProviderInfo info = new ProviderInfo();
-        info.authority = TvContractCompat.AUTHORITY;
-        QueryExceptionProvider provider =
-                Robolectric.buildContentProvider(QueryExceptionProvider.class).create(info).get();
-        ShadowContentResolver.registerProviderInternal(TvContractCompat.AUTHORITY, provider);
-
-        PreviewDataManager previewDataManager =
-                new PreviewDataManager(RuntimeEnvironment.application);
-        assertThat(previewDataManager.isLoadFinished()).isFalse();
-        previewDataManager.start();
-        List<ShadowLog.LogItem> logs = ShadowLog.getLogsForTag("PreviewDataManager");
-        // The only warning should be the test one
-        // NOTE: I am not using hamcrest matchers because of weird class loading issues
-        // TODO: use truth
-        for (ShadowLog.LogItem log : logs) {
-            if (log.type == Log.WARN) {
-                assertThat(log.msg).isEqualTo("Unable to get preview data");
-                assertThat(log.throwable).isInstanceOf(SQLException.class);
-                assertThat(log.throwable)
-                        .hasMessageThat()
-                        .isEqualTo("Testing content://android.media.tv/channel?preview=true");
-            }
-        }
-    }
-
-    @Test
-    public void createPreviewProgram_fromProgram() {
-        Program program =
-                new ProgramImpl.Builder()
-                        .setId(FAKE_PROGRAM_ID)
-                        .setTitle(FAKE_PROGRAM_TITLE)
-                        .setPosterArtUri(FAKE_PROGRAM_POSTER_URI)
-                        .build();
-        Channel channel =
-                new ChannelImpl.Builder()
-                        .setId(FAKE_CHANNEL_ID)
-                        .setDisplayName(FAKE_CHANNEL_DISPLAY_NAME)
-                        .setInputId(FAKE_INPUT_ID)
-                        .build();
-
-        PreviewProgram previewProgram =
-                PreviewDataManager.PreviewDataUtils.createPreviewProgramFromContent(
-                        PreviewProgramContent.createFromProgram(
-                                FAKE_PREVIEW_CHANNEL_ID, program, channel),
-                        0);
-
-        assertThat(previewProgram.getChannelId()).isEqualTo(FAKE_PREVIEW_CHANNEL_ID);
-        assertThat(previewProgram.getType())
-                .isEqualTo(TvContractCompat.PreviewPrograms.TYPE_CHANNEL);
-        assertThat(previewProgram.isLive()).isTrue();
-        assertThat(previewProgram.getTitle()).isEqualTo(FAKE_PROGRAM_TITLE);
-        assertThat(previewProgram.getDescription()).isEqualTo(FAKE_CHANNEL_DISPLAY_NAME);
-        assertThat(previewProgram.getPosterArtUri().toString()).isEqualTo(FAKE_PROGRAM_POSTER_URI);
-        assertThat(previewProgram.getIntentUri()).isEqualTo(channel.getUri());
-        assertThat(previewProgram.getPreviewVideoUri())
-                .isEqualTo(
-                        PreviewDataManager.PreviewDataUtils.addQueryParamToUri(
-                                channel.getUri(),
-                                Pair.create(PreviewProgramContent.PARAM_INPUT, FAKE_INPUT_ID)));
-        assertThat(previewProgram.getInternalProviderId())
-                .isEqualTo(Long.toString(FAKE_PROGRAM_ID));
-        assertThat(previewProgram.getContentId()).isEqualTo(channel.getUri().toString());
-    }
-
-    @Test
-    public void createPreviewProgram_fromRecordedProgram() {
-        RecordedProgram program =
-                RecordedProgram.builder()
-                        .setId(FAKE_PROGRAM_ID)
-                        .setTitle(FAKE_PROGRAM_TITLE)
-                        .setPosterArtUri(FAKE_PROGRAM_POSTER_URI)
-                        .setInputId(FAKE_INPUT_ID)
-                        .build();
-        Uri recordedProgramUri = TvContractCompat.buildRecordedProgramUri(FAKE_PROGRAM_ID);
-
-        PreviewProgram previewProgram =
-                PreviewDataManager.PreviewDataUtils.createPreviewProgramFromContent(
-                        PreviewProgramContent.createFromRecordedProgram(
-                                FAKE_PREVIEW_CHANNEL_ID, program, null),
-                        0);
-
-        assertThat(previewProgram.getChannelId()).isEqualTo(FAKE_PREVIEW_CHANNEL_ID);
-        assertThat(previewProgram.getType()).isEqualTo(TvContractCompat.PreviewPrograms.TYPE_CLIP);
-        assertThat(previewProgram.isLive()).isFalse();
-        assertThat(previewProgram.getTitle()).isEqualTo(FAKE_PROGRAM_TITLE);
-        assertThat(previewProgram.getDescription()).isEmpty();
-        assertThat(previewProgram.getPosterArtUri().toString()).isEqualTo(FAKE_PROGRAM_POSTER_URI);
-        assertThat(previewProgram.getIntentUri()).isEqualTo(recordedProgramUri);
-        assertThat(previewProgram.getPreviewVideoUri())
-                .isEqualTo(
-                        PreviewDataManager.PreviewDataUtils.addQueryParamToUri(
-                                recordedProgramUri,
-                                Pair.create(PreviewProgramContent.PARAM_INPUT, FAKE_INPUT_ID)));
-        assertThat(previewProgram.getContentId()).isEqualTo(recordedProgramUri.toString());
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/data/ProgramDataManagerTest.java b/tests/robotests/src/com/android/tv/data/ProgramDataManagerTest.java
deleted file mode 100644
index 2176aa9..0000000
--- a/tests/robotests/src/com/android/tv/data/ProgramDataManagerTest.java
+++ /dev/null
@@ -1,316 +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.data;
-
-import static android.os.Looper.getMainLooper;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
-
-import static org.robolectric.Shadows.shadowOf;
-
-import android.content.ContentResolver;
-import android.media.tv.TvContract;
-
-import com.android.tv.common.flags.impl.DefaultBackendKnobsFlags;
-import com.android.tv.data.api.Program;
-import com.android.tv.perf.stub.StubPerformanceMonitor;
-import com.android.tv.testing.FakeTvInputManagerHelper;
-import com.android.tv.testing.TestSingletonApp;
-import com.android.tv.testing.constants.ConfigConstants;
-import com.android.tv.testing.constants.Constants;
-import com.android.tv.testing.data.ProgramInfo;
-import com.android.tv.testing.data.ProgramUtils;
-import com.android.tv.testing.fakes.FakeClock;
-import com.android.tv.testing.fakes.FakeTvProvider;
-import com.android.tv.testing.robo.ContentProviders;
-import com.android.tv.testing.testdata.TestData;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.android.util.concurrent.RoboExecutorService;
-import org.robolectric.annotation.Config;
-
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-/** Test for {@link ProgramDataManager} */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK, application = TestSingletonApp.class)
-public class ProgramDataManagerTest {
-
-    // Wait time for expected success.
-    private static final long WAIT_TIME_OUT_MS = 1000L;
-    // Wait time for expected failure.
-    private static final long FAILURE_TIME_OUT_MS = 300L;
-
-    private ProgramDataManager mProgramDataManager;
-    private FakeClock mClock;
-    private TestProgramDataManagerCallback mCallback;
-
-    @Before
-    public void setUp() {
-        mClock = FakeClock.createWithCurrentTime();
-        mCallback = new TestProgramDataManagerCallback();
-        ContentProviders.register(FakeTvProvider.class, TvContract.AUTHORITY);
-        TestData.DEFAULT_10_CHANNELS.init(
-                RuntimeEnvironment.application, mClock, TimeUnit.DAYS.toMillis(1));
-        FakeTvInputManagerHelper tvInputManagerHelper =
-                new FakeTvInputManagerHelper(RuntimeEnvironment.application);
-        RoboExecutorService executor = new RoboExecutorService();
-        ContentResolver contentResolver = RuntimeEnvironment.application.getContentResolver();
-        ChannelDataManager channelDataManager =
-                new ChannelDataManager(
-                        RuntimeEnvironment.application,
-                        tvInputManagerHelper,
-                        executor,
-                        contentResolver);
-        mProgramDataManager =
-                new ProgramDataManager(
-                        RuntimeEnvironment.application,
-                        executor,
-                        RuntimeEnvironment.application.getContentResolver(),
-                        mClock,
-                        getMainLooper(),
-                        new DefaultBackendKnobsFlags(),
-                        new StubPerformanceMonitor(),
-                        channelDataManager,
-                        tvInputManagerHelper);
-
-        mProgramDataManager.setPrefetchEnabled(true);
-        mProgramDataManager.addCallback(mCallback);
-    }
-
-    @After
-    public void tearDown() {
-        mProgramDataManager.stop();
-    }
-
-    private void startAndWaitForComplete() throws InterruptedException {
-        mProgramDataManager.start();
-        shadowOf(getMainLooper()).idle();
-        assertThat(mCallback.channelUpdatedLatch.await(WAIT_TIME_OUT_MS, TimeUnit.MILLISECONDS))
-                .isTrue();
-    }
-
-    /** 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(RuntimeEnvironment.application, index);
-            assertThat(startTimeMs).isAtMost(mClock.currentTimeMillis());
-            assertThat(mClock.currentTimeMillis()).isLessThan(startTimeMs + programAt.durationMs);
-        }
-    }
-
-    /**
-     * Test for following methods.
-     *
-     * <p>{@link ProgramDataManager#getCurrentProgram(long)}, {@link
-     * ProgramDataManager#getPrograms(long, long)}, {@link
-     * ProgramDataManager#setPrefetchTimeRange(long)}.
-     */
-    @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;
-        mClock.setCurrentTimeMillis(prefetchTimeRangeStartMs + preventSnapDelayMs);
-        mProgramDataManager.setPrefetchTimeRange(prefetchTimeRangeStartMs);
-
-        startAndWaitForComplete();
-
-        for (long channelId = 1; channelId <= Constants.UNIT_TEST_CHANNEL_COUNT; channelId++) {
-            Program currentProgram = mProgramDataManager.getCurrentProgram(channelId);
-            // Test {@link ProgramDataManager#getCurrentProgram(long)}.
-            assertThat(currentProgram).isNotNull();
-            assertWithMessage("currentProgramStartTime")
-                    .that(currentProgram.getStartTimeUtcMillis())
-                    .isLessThan(mClock.currentTimeMillis());
-            assertWithMessage("currentProgramEndTime")
-                    .that(currentProgram.getEndTimeUtcMillis())
-                    .isGreaterThan(mClock.currentTimeMillis());
-
-            // Test {@link ProgramDataManager#getPrograms(long)}.
-            // Case #1: Normal case
-            List<Program> programs =
-                    mProgramDataManager.getPrograms(channelId, mClock.currentTimeMillis());
-            ProgramInfo stub = ProgramInfo.create();
-            int index = stub.getIndex(mClock.currentTimeMillis(), channelId);
-            for (Program program : programs) {
-                ProgramInfo programInfoAt = stub.build(RuntimeEnvironment.application, index);
-                long startTimeMs = stub.getStartTimeMs(index, channelId);
-                assertProgramEquals(startTimeMs, programInfoAt, program);
-                index++;
-            }
-            // Case #2: Corner cases where there's a program that starts at the start of the range.
-            long startTimeMs = programs.get(0).getStartTimeUtcMillis();
-            programs = mProgramDataManager.getPrograms(channelId, startTimeMs);
-            assertThat(programs.get(0).getStartTimeUtcMillis()).isEqualTo(startTimeMs);
-
-            // Test {@link ProgramDataManager#setPrefetchTimeRange(long)}.
-            programs =
-                    mProgramDataManager.getPrograms(
-                            channelId, prefetchTimeRangeStartMs - TimeUnit.HOURS.toMillis(1));
-            for (Program program : programs) {
-                assertThat(program.getEndTimeUtcMillis()).isAtLeast(prefetchTimeRangeStartMs);
-            }
-        }
-    }
-
-    /**
-     * Test for following methods.
-     *
-     * <p>{@link ProgramDataManager#addOnCurrentProgramUpdatedListener}, {@link
-     * ProgramDataManager#removeOnCurrentProgramUpdatedListener}.
-     */
-    @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(RuntimeEnvironment.application, index + 1);
-        mClock.setCurrentTimeMillis(nextProgramStartTimeMs - (WAIT_TIME_OUT_MS / 2));
-
-        startAndWaitForComplete();
-        // Note that changing current time doesn't affect the current program
-        // because current program is updated after waiting for the program's duration.
-        // See {@link ProgramDataManager#updateCurrentProgram}.
-        TestProgramDataManagerOnCurrentProgramUpdatedListener listener =
-                new TestProgramDataManagerOnCurrentProgramUpdatedListener();
-        mClock.setCurrentTimeMillis(mClock.currentTimeMillis() + WAIT_TIME_OUT_MS);
-        mProgramDataManager.addOnCurrentProgramUpdatedListener(testChannelId, listener);
-        shadowOf(getMainLooper()).runToEndOfTasks();
-        assertThat(
-                        listener.currentProgramUpdatedLatch.await(
-                                WAIT_TIME_OUT_MS, TimeUnit.MILLISECONDS))
-                .isTrue();
-        assertThat(listener.updatedChannelId).isEqualTo(testChannelId);
-        Program currentProgram = mProgramDataManager.getCurrentProgram(testChannelId);
-        assertProgramEquals(nextProgramStartTimeMs, nextProgramInfo, currentProgram);
-        assertThat(currentProgram).isEqualTo(listener.updatedProgram);
-    }
-
-    /** Test if program data is refreshed after the program insertion. */
-    @Test
-    public void testContentProviderUpdate() throws InterruptedException {
-        final long testChannelId = 1;
-        startAndWaitForComplete();
-        // Force program data manager to update program data whenever it's changes.
-        mProgramDataManager.setProgramPrefetchUpdateWait(0);
-        mCallback.reset();
-        List<Program> programList =
-                mProgramDataManager.getPrograms(testChannelId, mClock.currentTimeMillis());
-        assertThat(programList).isNotNull();
-        long lastProgramEndTime = programList.get(programList.size() - 1).getEndTimeUtcMillis();
-        // Make change in content provider
-        ProgramUtils.populatePrograms(
-                RuntimeEnvironment.application,
-                TvContract.buildChannelUri(testChannelId),
-                ProgramInfo.create(),
-                mClock,
-                TimeUnit.DAYS.toMillis(2));
-        shadowOf(getMainLooper()).runToEndOfTasks();
-        assertThat(mCallback.programUpdatedLatch.await(WAIT_TIME_OUT_MS, TimeUnit.MILLISECONDS))
-                .isTrue();
-        programList = mProgramDataManager.getPrograms(testChannelId, mClock.currentTimeMillis());
-        assertThat(lastProgramEndTime)
-                .isLessThan(programList.get(programList.size() - 1).getEndTimeUtcMillis());
-    }
-
-    /** Test for {@link ProgramDataManager#setPauseProgramUpdate(boolean)}. */
-    @Test
-    public void testSetPauseProgramUpdate() throws InterruptedException {
-        final long testChannelId = 1;
-        startAndWaitForComplete();
-        // Force program data manager to update program data whenever it's changes.
-        mProgramDataManager.setProgramPrefetchUpdateWait(0);
-        mCallback.reset();
-        mProgramDataManager.setPauseProgramUpdate(true);
-        ProgramUtils.populatePrograms(
-                RuntimeEnvironment.application,
-                TvContract.buildChannelUri(testChannelId),
-                ProgramInfo.create(),
-                mClock,
-                TimeUnit.DAYS.toMillis(2));
-        shadowOf(getMainLooper()).runToEndOfTasks();
-        assertThat(mCallback.programUpdatedLatch.await(FAILURE_TIME_OUT_MS, TimeUnit.MILLISECONDS))
-                .isFalse();
-    }
-
-    public static void assertProgramEquals(
-            long expectedStartTime, ProgramInfo expectedInfo, Program actualProgram) {
-        assertWithMessage("title").that(actualProgram.getTitle()).isEqualTo(expectedInfo.title);
-        assertWithMessage("episode")
-                .that(actualProgram.getEpisodeTitle())
-                .isEqualTo(expectedInfo.episode);
-        assertWithMessage("description")
-                .that(actualProgram.getDescription())
-                .isEqualTo(expectedInfo.description);
-        assertWithMessage("startTime")
-                .that(actualProgram.getStartTimeUtcMillis())
-                .isEqualTo(expectedStartTime);
-        assertWithMessage("endTime")
-                .that(actualProgram.getEndTimeUtcMillis())
-                .isEqualTo(expectedStartTime + expectedInfo.durationMs);
-    }
-
-    private static class TestProgramDataManagerCallback implements ProgramDataManager.Callback {
-        public CountDownLatch programUpdatedLatch = new CountDownLatch(1);
-        public CountDownLatch channelUpdatedLatch = new CountDownLatch(1);
-
-        @Override
-        public void onProgramUpdated() {
-            programUpdatedLatch.countDown();
-        }
-
-        @Override
-        public void onChannelUpdated() {
-            channelUpdatedLatch.countDown();
-        }
-
-        public void reset() {
-            programUpdatedLatch = new CountDownLatch(1);
-            channelUpdatedLatch = new CountDownLatch(1);
-        }
-    }
-
-    private static class TestProgramDataManagerOnCurrentProgramUpdatedListener
-            implements OnCurrentProgramUpdatedListener {
-        public final CountDownLatch currentProgramUpdatedLatch = new CountDownLatch(1);
-        public long updatedChannelId = -1;
-        public Program updatedProgram = null;
-
-        @Override
-        public void onCurrentProgramUpdated(long channelId, Program program) {
-            updatedChannelId = channelId;
-            updatedProgram = program;
-            currentProgramUpdatedLatch.countDown();
-        }
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/data/ProgramTest.java b/tests/robotests/src/com/android/tv/data/ProgramTest.java
deleted file mode 100644
index 407cca9..0000000
--- a/tests/robotests/src/com/android/tv/data/ProgramTest.java
+++ /dev/null
@@ -1,276 +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.data;
-
-import static android.media.tv.TvContract.Programs.Genres.COMEDY;
-import static android.media.tv.TvContract.Programs.Genres.FAMILY_KIDS;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
-
-import android.media.tv.TvContentRating;
-import android.media.tv.TvContract.Programs.Genres;
-import android.os.Parcel;
-
-import com.android.tv.data.api.Program;
-import com.android.tv.data.api.Program.CriticScore;
-import com.android.tv.testing.TvRobolectricTestRunner;
-import com.android.tv.testing.constants.ConfigConstants;
-
-import com.google.common.collect.ImmutableList;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/** Tests for {@link ProgramImpl}. */
-@RunWith(TvRobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-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 ProgramImpl.Builder().build();
-        assertWithMessage("isValid").that(program.isValid()).isFalse();
-    }
-
-    @Test
-    public void testNoGenres() {
-        Program program = new ProgramImpl.Builder().setCanonicalGenres("").build();
-        assertNullCanonicalGenres(program);
-        assertHasGenre(program, NOT_FOUND_GENRE, false);
-        assertHasGenre(program, FAMILY_GENRE_ID, false);
-        assertHasGenre(program, COMEDY_GENRE_ID, false);
-        assertHasGenre(program, GenreItems.ID_ALL_CHANNELS, true);
-    }
-
-    @Test
-    public void testFamilyGenre() {
-        Program program = new ProgramImpl.Builder().setCanonicalGenres(FAMILY_KIDS).build();
-        assertCanonicalGenres(program, FAMILY_KIDS);
-        assertHasGenre(program, NOT_FOUND_GENRE, false);
-        assertHasGenre(program, FAMILY_GENRE_ID, true);
-        assertHasGenre(program, COMEDY_GENRE_ID, false);
-        assertHasGenre(program, GenreItems.ID_ALL_CHANNELS, true);
-    }
-
-    @Test
-    public void testFamilyComedyGenre() {
-        Program program =
-                new ProgramImpl.Builder().setCanonicalGenres(FAMILY_KIDS + ", " + COMEDY).build();
-        assertCanonicalGenres(program, FAMILY_KIDS, COMEDY);
-        assertHasGenre(program, NOT_FOUND_GENRE, false);
-        assertHasGenre(program, FAMILY_GENRE_ID, true);
-        assertHasGenre(program, COMEDY_GENRE_ID, true);
-        assertHasGenre(program, GenreItems.ID_ALL_CHANNELS, true);
-    }
-
-    @Test
-    public void testOtherGenre() {
-        Program program = new ProgramImpl.Builder().setCanonicalGenres("other").build();
-        assertCanonicalGenres(program);
-        assertHasGenre(program, NOT_FOUND_GENRE, false);
-        assertHasGenre(program, FAMILY_GENRE_ID, false);
-        assertHasGenre(program, COMEDY_GENRE_ID, false);
-        assertHasGenre(program, GenreItems.ID_ALL_CHANNELS, true);
-    }
-
-    @Test
-    public void testParcelable() {
-        List<CriticScore> criticScores = new ArrayList<>();
-        criticScores.add(new CriticScore("1", "2", "3"));
-        criticScores.add(new CriticScore("4", "5", "6"));
-        ImmutableList<TvContentRating> ratings =
-                ImmutableList.of(
-                        TvContentRating.unflattenFromString("1/2/3"),
-                        TvContentRating.unflattenFromString("4/5/6"));
-        ProgramImpl p =
-                new ProgramImpl.Builder()
-                        .setId(1)
-                        .setPackageName("2")
-                        .setChannelId(3)
-                        .setTitle("4")
-                        .setSeriesId("5")
-                        .setEpisodeTitle("6")
-                        .setSeasonNumber("7")
-                        .setSeasonTitle("8")
-                        .setEpisodeNumber("9")
-                        .setStartTimeUtcMillis(10)
-                        .setEndTimeUtcMillis(11)
-                        .setDescription("12")
-                        .setLongDescription("12-long")
-                        .setVideoWidth(13)
-                        .setVideoHeight(14)
-                        .setCriticScores(criticScores)
-                        .setPosterArtUri("15")
-                        .setThumbnailUri("16")
-                        .setCanonicalGenres(Genres.encode(Genres.SPORTS, Genres.SHOPPING))
-                        .setContentRatings(ratings)
-                        .setRecordingProhibited(true)
-                        .build();
-        Parcel p1 = Parcel.obtain();
-        Parcel p2 = Parcel.obtain();
-        try {
-            p.writeToParcel(p1, 0);
-            byte[] bytes = p1.marshall();
-            p2.unmarshall(bytes, 0, bytes.length);
-            p2.setDataPosition(0);
-            ProgramImpl r2 = ProgramImpl.fromParcel(p2);
-            assertThat(r2).isEqualTo(p);
-        } finally {
-            p1.recycle();
-            p2.recycle();
-        }
-    }
-
-    @Test
-    public void testParcelableWithCriticScore() {
-        ProgramImpl program =
-                new ProgramImpl.Builder()
-                        .setTitle("MyTitle")
-                        .addCriticScore(
-                                new CriticScore(
-                                        "default source", "5/10", "http://testurl/testimage.jpg"))
-                        .build();
-        Parcel parcel = Parcel.obtain();
-        program.writeToParcel(parcel, 0);
-        parcel.setDataPosition(0);
-        Program programFromParcel = ProgramImpl.CREATOR.createFromParcel(parcel);
-
-        assertThat(programFromParcel.getCriticScores()).isNotNull();
-        assertThat(programFromParcel.getCriticScores().get(0).source).isEqualTo("default source");
-        assertThat(programFromParcel.getCriticScores().get(0).score).isEqualTo("5/10");
-        assertThat(programFromParcel.getCriticScores().get(0).logoUrl)
-                .isEqualTo("http://testurl/testimage.jpg");
-    }
-
-    @Test
-    public void getEpisodeContentDescription_blank() {
-        Program program = new ProgramImpl.Builder().build();
-        assertThat(program.getEpisodeContentDescription(RuntimeEnvironment.application)).isNull();
-    }
-
-    @Test
-    public void getEpisodeContentDescription_seasonEpisodeAndTitle() {
-        Program program =
-                new ProgramImpl.Builder()
-                        .setSeasonNumber("1")
-                        .setEpisodeNumber("2")
-                        .setEpisodeTitle("The second one")
-                        .build();
-        assertThat(program.getEpisodeContentDescription(RuntimeEnvironment.application))
-                .isEqualTo("Season 1 Episode 2 The second one");
-    }
-
-    @Test
-    public void getEpisodeContentDescription_EpisodeAndTitle() {
-        Program program =
-                new ProgramImpl.Builder()
-                        .setEpisodeNumber("2")
-                        .setEpisodeTitle("The second one")
-                        .build();
-        assertThat(program.getEpisodeContentDescription(RuntimeEnvironment.application))
-                .isEqualTo("Episode 2 The second one");
-    }
-
-    @Test
-    public void getEpisodeContentDescription_seasonEpisode() {
-        Program program =
-                new ProgramImpl.Builder().setSeasonNumber("1").setEpisodeNumber("2").build();
-        assertThat(program.getEpisodeContentDescription(RuntimeEnvironment.application))
-                .isEqualTo("Season 1 Episode 2 ");
-    }
-
-    @Test
-    public void getEpisodeContentDescription_EpisodeTitle() {
-        Program program = new ProgramImpl.Builder().setEpisodeTitle("The second one").build();
-        assertThat(program.getEpisodeContentDescription(RuntimeEnvironment.application))
-                .isEqualTo("The second one");
-    }
-
-    @Test
-    public void getEpisodeDisplayTitle_blank() {
-        Program program = new ProgramImpl.Builder().build();
-        assertThat(program.getEpisodeDisplayTitle(RuntimeEnvironment.application)).isNull();
-    }
-
-    @Test
-    public void getEpisodeDisplayTitle_seasonEpisodeAndTitle() {
-        Program program =
-                new ProgramImpl.Builder()
-                        .setSeasonNumber("1")
-                        .setEpisodeNumber("2")
-                        .setEpisodeTitle("The second one")
-                        .build();
-        assertThat(program.getEpisodeDisplayTitle(RuntimeEnvironment.application))
-                .isEqualTo("S1: Ep. 2 The second one");
-    }
-
-    @Test
-    public void getEpisodeDisplayTitle_EpisodeTitle() {
-        Program program =
-                new ProgramImpl.Builder()
-                        .setEpisodeNumber("2")
-                        .setEpisodeTitle("The second one")
-                        .build();
-        assertThat(program.getEpisodeDisplayTitle(RuntimeEnvironment.application))
-                .isEqualTo("Ep. 2 The second one");
-    }
-
-    @Test
-    public void getEpisodeDisplayTitle_seasonEpisode() {
-        Program program =
-                new ProgramImpl.Builder().setSeasonNumber("1").setEpisodeNumber("2").build();
-        assertThat(program.getEpisodeDisplayTitle(RuntimeEnvironment.application))
-                .isEqualTo("S1: Ep. 2 ");
-    }
-
-    @Test
-    public void getEpisodeDisplayTitle_episode() {
-        Program program = new ProgramImpl.Builder().setEpisodeTitle("The second one").build();
-        assertThat(program.getEpisodeDisplayTitle(RuntimeEnvironment.application))
-                .isEqualTo("The second one");
-    }
-
-    private static void assertNullCanonicalGenres(Program program) {
-        String[] actual = program.getCanonicalGenres();
-        assertWithMessage("Expected null canonical genres but was " + Arrays.toString(actual))
-                .that(actual)
-                .isNull();
-    }
-
-    private static void assertCanonicalGenres(Program program, String... expected) {
-        assertWithMessage("canonical genres")
-                .that(Arrays.asList(program.getCanonicalGenres()))
-                .isEqualTo(Arrays.asList(expected));
-    }
-
-    private static void assertHasGenre(Program program, int genreId, boolean expected) {
-        assertWithMessage("hasGenre(" + genreId + ")")
-                .that(program.hasGenre(genreId))
-                .isEqualTo(expected);
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/data/TvInputNewComparatorTest.java b/tests/robotests/src/com/android/tv/data/TvInputNewComparatorTest.java
deleted file mode 100644
index 201fa03..0000000
--- a/tests/robotests/src/com/android/tv/data/TvInputNewComparatorTest.java
+++ /dev/null
@@ -1,102 +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.data;
-
-import android.content.pm.ResolveInfo;
-import android.media.tv.TvInputInfo;
-import android.util.Pair;
-
-import com.android.tv.testing.ComparatorTester;
-import com.android.tv.testing.constants.ConfigConstants;
-import com.android.tv.testing.utils.TestUtils;
-import com.android.tv.util.SetupUtils;
-import com.android.tv.util.TvInputManagerHelper;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentMatchers;
-import org.mockito.Mockito;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-import java.util.Comparator;
-import java.util.LinkedHashMap;
-
-/** Test for {@link TvInputNewComparator} */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-public class TvInputNewComparatorTest {
-    @Test
-    public void testComparator() throws Exception {
-        LinkedHashMap<String, Pair<Boolean, Boolean>> inputIdToNewInput = new LinkedHashMap<>();
-        inputIdToNewInput.put("2_new_input", Pair.create(true, false));
-        inputIdToNewInput.put("4_new_input", Pair.create(true, false));
-        inputIdToNewInput.put("4_old_input", Pair.create(false, false));
-        inputIdToNewInput.put("0_old_input", Pair.create(false, true));
-        inputIdToNewInput.put("1_old_input", Pair.create(false, true));
-        inputIdToNewInput.put("3_old_input", Pair.create(false, true));
-
-        SetupUtils setupUtils = Mockito.mock(SetupUtils.class);
-        Mockito.when(setupUtils.isNewInput(ArgumentMatchers.anyString()))
-                .thenAnswer(
-                        new Answer<Boolean>() {
-                            @Override
-                            public Boolean answer(InvocationOnMock invocation) throws Throwable {
-                                String inputId = (String) invocation.getArguments()[0];
-                                return inputIdToNewInput.get(inputId).first;
-                            }
-                        });
-        Mockito.when(setupUtils.isSetupDone(ArgumentMatchers.anyString()))
-                .thenAnswer(
-                        new Answer<Boolean>() {
-                            @Override
-                            public Boolean answer(InvocationOnMock invocation) throws Throwable {
-                                String inputId = (String) invocation.getArguments()[0];
-                                return inputIdToNewInput.get(inputId).second;
-                            }
-                        });
-        TvInputManagerHelper inputManager = Mockito.mock(TvInputManagerHelper.class);
-        Mockito.when(inputManager.getDefaultTvInputInfoComparator())
-                .thenReturn(
-                        new Comparator<TvInputInfo>() {
-                            @Override
-                            public int compare(TvInputInfo lhs, TvInputInfo rhs) {
-                                return lhs.getId().compareTo(rhs.getId());
-                            }
-                        });
-        TvInputNewComparator comparator = new TvInputNewComparator(setupUtils, inputManager);
-        ComparatorTester comparatorTester =
-                new ComparatorTester(comparator).permitInconsistencyWithEquals();
-        ResolveInfo resolveInfo = TestUtils.createResolveInfo("test", "test");
-        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);
-            TvInputInfo info2 =
-                    TestUtils.createTvInputInfo(
-                            resolveInfo, id, "test2", TvInputInfo.TYPE_DISPLAY_PORT, true);
-            TvInputInfo info3 =
-                    TestUtils.createTvInputInfo(
-                            resolveInfo, id, "test", TvInputInfo.TYPE_HDMI, true);
-            comparatorTester.addEqualityGroup(info1, info2, info3);
-        }
-        comparatorTester.testCompare();
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/data/WatchedHistoryManagerTest.java b/tests/robotests/src/com/android/tv/data/WatchedHistoryManagerTest.java
deleted file mode 100644
index 761827a..0000000
--- a/tests/robotests/src/com/android/tv/data/WatchedHistoryManagerTest.java
+++ /dev/null
@@ -1,144 +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.data;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.tv.data.WatchedHistoryManager.WatchedRecord;
-import com.android.tv.testing.constants.ConfigConstants;
-
-import com.google.common.util.concurrent.MoreExecutors;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-import java.util.concurrent.TimeUnit;
-
-/** Test for {@link WatchedHistoryManagerTest}. */
-@SmallTest
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-public class WatchedHistoryManagerTest {
-    // Wait time for expected success.
-    private static final int MAX_HISTORY_SIZE = 100;
-
-    private WatchedHistoryManager mWatchedHistoryManager;
-    private TestWatchedHistoryManagerListener mListener;
-
-    @Before
-    public void setUp() {
-        mWatchedHistoryManager =
-                new WatchedHistoryManager(
-                        RuntimeEnvironment.application,
-                        MAX_HISTORY_SIZE,
-                        MoreExecutors.directExecutor());
-        mListener = new TestWatchedHistoryManagerListener();
-        mWatchedHistoryManager.setListener(mListener);
-    }
-
-    private void startAndWaitForComplete() {
-        mWatchedHistoryManager.start();
-        assertThat(mListener.mLoadFinished).isTrue();
-    }
-
-    @Test
-    public void testIsLoaded() {
-        startAndWaitForComplete();
-        assertThat(mWatchedHistoryManager.isLoaded()).isTrue();
-    }
-
-    @Test
-    public void testLogChannelViewStop() {
-        startAndWaitForComplete();
-        long fakeId = 100000000;
-        long time = System.currentTimeMillis();
-        long duration = TimeUnit.MINUTES.toMillis(10);
-        ChannelImpl channel = new ChannelImpl.Builder().setId(fakeId).build();
-        mWatchedHistoryManager.logChannelViewStop(channel, time, duration);
-
-        WatchedRecord record = mWatchedHistoryManager.getRecord(0);
-        WatchedRecord recordFromSharedPreferences =
-                mWatchedHistoryManager.getRecordFromSharedPreferences(0);
-        assertThat(fakeId).isEqualTo(record.channelId);
-        assertThat(time - duration).isEqualTo(record.watchedStartTime);
-        assertThat(duration).isEqualTo(record.duration);
-        assertThat(recordFromSharedPreferences).isEqualTo(record);
-    }
-
-    @Test
-    public void testCircularHistoryQueue() {
-        startAndWaitForComplete();
-        final long startChannelId = 100000000;
-        long time = System.currentTimeMillis();
-        long duration = TimeUnit.MINUTES.toMillis(10);
-
-        int size = MAX_HISTORY_SIZE * 2;
-        for (int i = 0; i < size; ++i) {
-            ChannelImpl channel = new ChannelImpl.Builder().setId(startChannelId + i).build();
-            mWatchedHistoryManager.logChannelViewStop(channel, time + duration * i, duration);
-        }
-        for (int i = 0; i < MAX_HISTORY_SIZE; ++i) {
-            WatchedRecord record = mWatchedHistoryManager.getRecord(i);
-            WatchedRecord recordFromSharedPreferences =
-                    mWatchedHistoryManager.getRecordFromSharedPreferences(i);
-            assertThat(recordFromSharedPreferences).isEqualTo(record);
-            assertThat(startChannelId + size - 1 - i).isEqualTo(record.channelId);
-        }
-        // Since the WatchedHistory is a circular queue, the value for 0 and maxHistorySize
-        // are same.
-        assertThat(mWatchedHistoryManager.getRecordFromSharedPreferences(MAX_HISTORY_SIZE))
-                .isEqualTo(mWatchedHistoryManager.getRecordFromSharedPreferences(0));
-    }
-
-    @Test
-    public void testWatchedRecordEquals() {
-        assertThat(new WatchedRecord(1, 2, 3).equals(new WatchedRecord(1, 2, 3))).isTrue();
-        assertThat(new WatchedRecord(1, 2, 3).equals(new WatchedRecord(1, 2, 4))).isFalse();
-        assertThat(new WatchedRecord(1, 2, 3).equals(new WatchedRecord(1, 4, 3))).isFalse();
-        assertThat(new WatchedRecord(1, 2, 3).equals(new WatchedRecord(4, 2, 3))).isFalse();
-    }
-
-    @Test
-    public void testEncodeDecodeWatchedRecord() {
-        long fakeId = 100000000;
-        long time = System.currentTimeMillis();
-        long duration = TimeUnit.MINUTES.toMillis(10);
-        WatchedRecord record = new WatchedRecord(fakeId, time, duration);
-        WatchedRecord sameRecord =
-                mWatchedHistoryManager.decode(mWatchedHistoryManager.encode(record));
-        assertThat(sameRecord).isEqualTo(record);
-    }
-
-    private static final class TestWatchedHistoryManagerListener
-            implements WatchedHistoryManager.Listener {
-        boolean mLoadFinished;
-
-        @Override
-        public void onLoadFinished() {
-            mLoadFinished = true;
-        }
-
-        @Override
-        public void onNewRecordAdded(WatchedRecord watchedRecord) {}
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/data/api/ProgramTest.java b/tests/robotests/src/com/android/tv/data/api/ProgramTest.java
deleted file mode 100644
index 3b9f062..0000000
--- a/tests/robotests/src/com/android/tv/data/api/ProgramTest.java
+++ /dev/null
@@ -1,119 +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.data.api;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import com.android.tv.data.ProgramImpl;
-import com.android.tv.testing.constants.ConfigConstants;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-/** Tests for {@link Program}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-public class ProgramTest {
-
-    private static ProgramImpl createProgramWithStartEndTimes(
-            long startTimeUtcMillis, long endTimeUtcMillis) {
-        return new ProgramImpl.Builder()
-                .setStartTimeUtcMillis(startTimeUtcMillis)
-                .setEndTimeUtcMillis(endTimeUtcMillis)
-                .build();
-    }
-
-    private static ProgramImpl createProgramWithChannelId(long channelId) {
-        return new ProgramImpl.Builder().setChannelId(channelId).build();
-    }
-
-    private final Program start10end20 = createProgramWithStartEndTimes(10, 20);
-    private final Program channel1 = createProgramWithChannelId(1);
-
-    @Test
-    public void sameChannel_nullAlwaysFalse() {
-        assertThat(Program.sameChannel(null, null)).isFalse();
-        assertThat(Program.sameChannel(channel1, null)).isFalse();
-        assertThat(Program.sameChannel(null, channel1)).isFalse();
-    }
-
-    @Test
-    public void sameChannel_true() {
-        assertThat(Program.sameChannel(channel1, channel1)).isTrue();
-        assertThat(Program.sameChannel(channel1, createProgramWithChannelId(1))).isTrue();
-    }
-
-    @Test
-    public void sameChannel_false() {
-        assertThat(Program.sameChannel(channel1, createProgramWithChannelId(2))).isFalse();
-    }
-
-    @Test
-    public void isOverLapping_nullAlwaysFalse() {
-        assertThat(Program.isOverlapping(null, null)).isFalse();
-        assertThat(Program.isOverlapping(start10end20, null)).isFalse();
-        assertThat(Program.isOverlapping(null, start10end20)).isFalse();
-    }
-
-    @Test
-    public void isOverLapping_same() {
-        assertThat(Program.isOverlapping(start10end20, start10end20)).isTrue();
-    }
-
-    @Test
-    public void isOverLapping_endBefore() {
-        assertThat(Program.isOverlapping(start10end20, createProgramWithStartEndTimes(1, 9)))
-                .isFalse();
-    }
-
-    @Test
-    public void isOverLapping_endAtStart() {
-        assertThat(Program.isOverlapping(start10end20, createProgramWithStartEndTimes(1, 10)))
-                .isFalse();
-    }
-
-    @Test
-    public void isOverLapping_endDuring() {
-        assertThat(Program.isOverlapping(start10end20, createProgramWithStartEndTimes(1, 11)))
-                .isTrue();
-    }
-
-    @Test
-    public void isOverLapping_startAfter() {
-        assertThat(Program.isOverlapping(start10end20, createProgramWithStartEndTimes(21, 30)))
-                .isFalse();
-    }
-
-    @Test
-    public void isOverLapping_beginAtEnd() {
-        assertThat(Program.isOverlapping(start10end20, createProgramWithStartEndTimes(20, 30)))
-                .isFalse();
-    }
-
-    @Test
-    public void isOverLapping_beginBeforeEnd() {
-        assertThat(Program.isOverlapping(start10end20, createProgramWithStartEndTimes(19, 30)))
-                .isTrue();
-    }
-
-    @Test
-    public void isOverLapping_inside() {
-        assertThat(Program.isOverlapping(start10end20, createProgramWithStartEndTimes(11, 19)))
-                .isTrue();
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/data/epg/EpgFetcherImplTest.java b/tests/robotests/src/com/android/tv/data/epg/EpgFetcherImplTest.java
deleted file mode 100644
index 91472d0..0000000
--- a/tests/robotests/src/com/android/tv/data/epg/EpgFetcherImplTest.java
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * 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;
-
-/** Tests for {@link EpgFetcher}. */
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.database.sqlite.SQLiteDatabase;
-import android.media.tv.TvContract;
-
-import androidx.tvprovider.media.tv.Channel;
-
-import com.android.tv.common.CommonPreferences;
-import com.android.tv.common.buildtype.HasBuildType.BuildType;
-import com.android.tv.common.flags.impl.DefaultBackendKnobsFlags;
-import com.android.tv.common.flags.impl.SettableFlagsModule;
-import com.android.tv.common.util.PostalCodeUtils;
-import com.android.tv.data.ChannelDataManager;
-import com.android.tv.features.TvFeatures;
-import com.android.tv.perf.PerformanceMonitor;
-import com.android.tv.perf.stub.StubPerformanceMonitor;
-import com.android.tv.testing.DbTestingUtils;
-import com.android.tv.testing.EpgTestData;
-import com.android.tv.testing.FakeEpgReader;
-import com.android.tv.testing.FakeTvInputManagerHelper;
-import com.android.tv.testing.TestSingletonApp;
-import com.android.tv.testing.constants.ConfigConstants;
-import com.android.tv.testing.fakes.FakeClock;
-import com.android.tv.testing.fakes.FakeTvProvider;
-import com.android.tv.testing.robo.ContentProviders;
-
-import com.google.android.tv.livechannels.epg.provider.EpgContentProvider;
-import com.google.android.tv.partner.support.EpgContract;
-import com.google.common.collect.ImmutableList;
-import com.android.tv.common.flags.proto.TypedFeatures.StringListParam;
-
-import dagger.Component;
-import dagger.Module;
-import dagger.android.AndroidInjectionModule;
-import dagger.android.AndroidInjector;
-import dagger.android.DispatchingAndroidInjector;
-import dagger.android.HasAndroidInjector;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.Shadows;
-import org.robolectric.android.util.concurrent.RoboExecutorService;
-import org.robolectric.annotation.Config;
-
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-
-import javax.inject.Inject;
-
-/** Tests for {@link EpgFetcherImpl}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK, application = EpgFetcherImplTest.TestApp.class)
-public class EpgFetcherImplTest {
-
-    /** TestApp for {@link EpgFetcherImplTest} */
-    public static class TestApp extends TestSingletonApp implements HasAndroidInjector {
-        @Inject DispatchingAndroidInjector<Object> dispatchingAndroidInjector;
-
-        @Override
-        public void onCreate() {
-            super.onCreate();
-            DaggerEpgFetcherImplTest_TestAppComponent.builder()
-                    .settableFlagsModule(flagsModule)
-                    .build()
-                    .inject(this);
-        }
-
-        @Override
-        public AndroidInjector<Object> androidInjector() {
-            return dispatchingAndroidInjector;
-        }
-    }
-
-    /** Component for {@link EpgFetcherImplTest} */
-    @Component(
-            modules = {
-                AndroidInjectionModule.class,
-                TestModule.class,
-                EpgContentProvider.Module.class
-            })
-    interface TestAppComponent extends AndroidInjector<TestApp> {}
-
-    /** Module for {@link EpgFetcherImplTest} */
-    @Module(includes = {SettableFlagsModule.class})
-    public static class TestModule {}
-
-    private static final String[] PROGRAM_COLUMNS = {
-        TvContract.Programs.COLUMN_CHANNEL_ID,
-        TvContract.Programs.COLUMN_TITLE,
-        TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS,
-        TvContract.Programs.COLUMN_END_TIME_UTC_MILLIS
-    };
-
-    private static final String[] CHANNEL_COLUMNS = {
-        TvContract.Channels.COLUMN_DISPLAY_NAME,
-        TvContract.Channels.COLUMN_DISPLAY_NUMBER,
-        TvContract.Channels.COLUMN_NETWORK_AFFILIATION
-    };
-
-    private FakeClock mFakeClock;
-    private EpgFetcherImpl mEpgFetcher;
-    private ChannelDataManager mChannelDataManager;
-    private FakeEpgReader mEpgReader;
-    private PerformanceMonitor mPerformanceMonitor = new StubPerformanceMonitor();
-    private ContentResolver mContentResolver;
-    private FakeTvProvider mTvProvider;
-    private EpgContentProvider mEpgProvider;
-    private EpgContentProvider.EpgDatabaseHelper mDatabaseHelper;
-    private TestApp mTestApp;
-
-    @Before
-    public void setup() {
-
-        TvFeatures.CLOUD_EPG_FOR_3RD_PARTY.enableForTest();
-        mTestApp = (TestApp) RuntimeEnvironment.application;
-        Shadows.shadowOf(RuntimeEnvironment.application)
-                .grantPermissions("com.android.providers.tv.permission.ACCESS_ALL_EPG_DATA");
-        mDatabaseHelper = new EpgContentProvider.EpgDatabaseHelper(RuntimeEnvironment.application);
-        CommonPreferences.initialize(RuntimeEnvironment.application);
-        PostalCodeUtils.setLastPostalCode(RuntimeEnvironment.application, "90210");
-        EpgFetchHelper.setLastLineupId(RuntimeEnvironment.application, "test90210");
-        mTvProvider = ContentProviders.register(FakeTvProvider.class, TvContract.AUTHORITY);
-        mEpgProvider = ContentProviders.register(EpgContentProvider.class, EpgContract.AUTHORITY);
-        mEpgProvider.setCallingPackage_("com.google.android.tv");
-        mFakeClock = FakeClock.createWithCurrentTime();
-        FakeTvInputManagerHelper fakeTvInputManagerHelper =
-                new FakeTvInputManagerHelper(RuntimeEnvironment.application);
-        mContentResolver = RuntimeEnvironment.application.getContentResolver();
-        mChannelDataManager =
-                new ChannelDataManager(
-                        RuntimeEnvironment.application,
-                        fakeTvInputManagerHelper,
-                        new RoboExecutorService(),
-                        mContentResolver);
-        fakeTvInputManagerHelper.start();
-        mChannelDataManager.start();
-        mEpgReader = new FakeEpgReader(mFakeClock);
-        mEpgFetcher =
-                new EpgFetcherImpl(
-                        RuntimeEnvironment.application,
-                        new EpgInputWhiteList(
-                                mTestApp.flagsModule.cloudEpgFlags,
-                                mTestApp.flagsModule.legacyFlags),
-                        mChannelDataManager,
-                        mEpgReader,
-                        mPerformanceMonitor,
-                        mFakeClock,
-                        new DefaultBackendKnobsFlags(),
-                        BuildType.NO_JNI_TEST);
-        EpgTestData.DATA_90210.loadData(mFakeClock, mEpgReader); // This also sets fake clock
-        EpgFetchHelper.setLastEpgUpdatedTimestamp(
-                RuntimeEnvironment.application,
-                mFakeClock.currentTimeMillis() - TimeUnit.DAYS.toMillis(1));
-    }
-
-    @After
-    public void after() {
-        mChannelDataManager.stop();
-        TvFeatures.CLOUD_EPG_FOR_3RD_PARTY.resetForTests();
-    }
-
-    @Test
-    public void fetchImmediately_nochannels() throws ExecutionException, InterruptedException {
-        EpgFetcherImpl.FetchAsyncTask fetcherTask = mEpgFetcher.createFetchTask(null, null);
-        fetcherTask.execute();
-
-        assertThat(fetcherTask.get()).isEqualTo(EpgFetcherImpl.REASON_NO_BUILT_IN_CHANNELS);
-        List<List<String>> rows =
-                DbTestingUtils.toList(
-                        mContentResolver.query(
-                                TvContract.Programs.CONTENT_URI,
-                                PROGRAM_COLUMNS,
-                                null,
-                                null,
-                                null));
-        assertThat(rows).isEmpty();
-    }
-
-    @Test
-    public void fetchImmediately_testChannel() throws ExecutionException, InterruptedException {
-        // The channels must be in the app package.
-        // For this test the package is com.android.tv.data.epg
-        insertTestChannels(
-                "com.android.tv.data.epg/.tuner.TunerTvInputService", EpgTestData.CHANNEL_10);
-        EpgFetcherImpl.FetchAsyncTask fetcherTask = mEpgFetcher.createFetchTask(null, null);
-        fetcherTask.execute();
-
-        assertThat(fetcherTask.get()).isNull();
-        List<List<String>> rows =
-                DbTestingUtils.toList(
-                        mContentResolver.query(
-                                TvContract.Programs.CONTENT_URI,
-                                PROGRAM_COLUMNS,
-                                null,
-                                null,
-                                null));
-        assertThat(rows)
-                .containsExactly(
-                        ImmutableList.of("1", "Program 1", "1496358000000", "1496359800000"));
-    }
-
-    @Test
-    public void fetchImmediately_epgChannel() throws ExecutionException, InterruptedException {
-        mTestApp.flagsModule.cloudEpgFlags.setThirdPartyEpgInputCsv("com.example/.Input");
-        insertTestChannels("com.example/.Input", EpgTestData.CHANNEL_10, EpgTestData.CHANNEL_11);
-        createTestEpgInput();
-        EpgFetcherImpl.FetchAsyncTask fetcherTask = mEpgFetcher.createFetchTask(null, null);
-        fetcherTask.execute();
-
-        assertThat(fetcherTask.get()).isNull();
-        List<List<String>> rows =
-                DbTestingUtils.toList(
-                        mContentResolver.query(
-                                TvContract.Programs.CONTENT_URI,
-                                PROGRAM_COLUMNS,
-                                null,
-                                null,
-                                null));
-        assertThat(rows)
-                .containsExactly(
-                        ImmutableList.of("1", "Program 1", "1496358000000", "1496359800000"),
-                        ImmutableList.of("2", "Program 2", "1496359800000", "1496361600000"));
-    }
-
-    @Test
-    public void testUpdateNetworkAffiliation() throws ExecutionException, InterruptedException {
-        if (!TvFeatures.STORE_NETWORK_AFFILIATION.isEnabled(RuntimeEnvironment.application)) {
-            return;
-        }
-        // set network affiliation to null so that it can be updated later
-        Channel channel =
-                new Channel.Builder(EpgTestData.CHANNEL_10).setNetworkAffiliation(null).build();
-        // The channels must be in the app package.
-        // For this test the package is com.android.tv.data.epg
-        insertTestChannels("com.android.tv.data.epg/.tuner.TunerTvInputService", channel);
-
-        List<List<String>> rows =
-                DbTestingUtils.toList(
-                        mContentResolver.query(
-                                TvContract.Channels.CONTENT_URI,
-                                CHANNEL_COLUMNS,
-                                null,
-                                null,
-                                null));
-        assertThat(rows).containsExactly(ImmutableList.of("Channel TEN", "10", "null"));
-        EpgFetcherImpl.FetchAsyncTask fetcherTask = mEpgFetcher.createFetchTask(null, null);
-        fetcherTask.execute();
-
-        assertThat(fetcherTask.get()).isNull();
-        rows =
-                DbTestingUtils.toList(
-                        mContentResolver.query(
-                                TvContract.Channels.CONTENT_URI,
-                                CHANNEL_COLUMNS,
-                                null,
-                                null,
-                                null));
-        // network affiliation should be updated
-        assertThat(rows)
-                .containsExactly(
-                        ImmutableList.of("Channel TEN", "10", "Channel 10 Network Affiliation"));
-    }
-
-    protected void insertTestChannels(String inputId, Channel... channels) {
-
-        for (Channel channel : channels) {
-            ContentValues values =
-                    new Channel.Builder(channel).setInputId(inputId).build().toContentValues();
-            String packageName = inputId.substring(0, inputId.indexOf('/'));
-            mTvProvider.setCallingPackage(packageName);
-            mContentResolver.insert(TvContract.Channels.CONTENT_URI, values);
-            mTvProvider.setCallingPackage("com.android.tv");
-        }
-    }
-
-    private void createTestEpgInput() {
-        // Use the database helper so we can set the package name.
-        SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();
-        ContentValues values = new ContentValues();
-        values.put(EpgContract.EpgInputs.COLUMN_ID, "1");
-        values.put(EpgContract.EpgInputs.COLUMN_PACKAGE_NAME, "com.example");
-        values.put(EpgContract.EpgInputs.COLUMN_INPUT_ID, "com.example/.Input");
-        values.put(EpgContract.EpgInputs.COLUMN_LINEUP_ID, "lineup1");
-        long rowId = db.insert("epg_input", null, values);
-        assertThat(rowId).isEqualTo(1);
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/data/epg/EpgInputWhiteListTest.java b/tests/robotests/src/com/android/tv/data/epg/EpgInputWhiteListTest.java
deleted file mode 100644
index d989b51..0000000
--- a/tests/robotests/src/com/android/tv/data/epg/EpgInputWhiteListTest.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * 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 static com.google.common.truth.Truth.assertThat;
-
-import com.android.tv.common.flags.impl.DefaultCloudEpgFlags;
-import com.android.tv.common.flags.impl.DefaultLegacyFlags;
-import com.android.tv.features.TvFeatures;
-import com.android.tv.testing.constants.ConfigConstants;
-import com.android.tv.common.flags.proto.TypedFeatures.StringListParam;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-/** Tests for {@link EpgInputWhiteList}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-public class EpgInputWhiteListTest {
-
-    private EpgInputWhiteList mWhiteList;
-    private DefaultCloudEpgFlags mCloudEpgFlags;
-    private DefaultLegacyFlags mLegacyFlags;
-
-    @Before
-    public void setup() {
-        TvFeatures.CLOUD_EPG_FOR_3RD_PARTY.enableForTest();
-        mCloudEpgFlags = new DefaultCloudEpgFlags();
-        mLegacyFlags = DefaultLegacyFlags.DEFAULT;
-        mWhiteList = new EpgInputWhiteList(mCloudEpgFlags, mLegacyFlags);
-    }
-
-    @After
-    public void after() {
-        TvFeatures.CLOUD_EPG_FOR_3RD_PARTY.resetForTests();
-    }
-
-    @Test
-    public void isInputWhiteListed_noRemoteConfig() {
-        assertThat(mWhiteList.isInputWhiteListed("com.example/.Foo")).isFalse();
-    }
-
-    @Test
-    public void isInputWhiteListed_noMatch() {
-        mCloudEpgFlags.setThirdPartyEpgInputCsv("com.example/.Bar");
-        assertThat(mWhiteList.isInputWhiteListed("com.example/.Foo")).isFalse();
-    }
-
-    @Test
-    public void isInputWhiteListed_match() {
-        mCloudEpgFlags.setThirdPartyEpgInputCsv("com.example/.Foo");
-        assertThat(mWhiteList.isInputWhiteListed("com.example/.Foo")).isTrue();
-    }
-
-    @Test
-    public void isInputWhiteListed_matchWithTwo() {
-        mCloudEpgFlags.setThirdPartyEpgInputCsv("com.example/.Foo,com.example/.Bar");
-        assertThat(mWhiteList.isInputWhiteListed("com.example/.Foo")).isTrue();
-    }
-
-    @Test
-    public void toInputSet_withNewLine() {
-        assertThat(EpgInputWhiteList.toInputSet("com.example/.Foo,\ncom.example/.Bar\n"))
-                .containsExactly("com.example/.Foo", "com.example/.Bar");
-    }
-
-    @Test
-    public void toInputSet_withWhiteSpace() {
-        assertThat(EpgInputWhiteList.toInputSet("com.example/.Foo , com.example/.Bar "))
-                .containsExactly("com.example/.Foo", "com.example/.Bar");
-    }
-
-    @Test
-    public void isPackageWhiteListed_noRemoteConfig() {
-        assertThat(mWhiteList.isPackageWhiteListed("com.example")).isFalse();
-    }
-
-    @Test
-    public void isPackageWhiteListed_noMatch() {
-        mCloudEpgFlags.setThirdPartyEpgInputCsv("com.example/.Bar");
-        assertThat(mWhiteList.isPackageWhiteListed("com.other")).isFalse();
-    }
-
-    @Test
-    public void isPackageWhiteListed_match() {
-        mCloudEpgFlags.setThirdPartyEpgInputCsv("com.example/.Foo");
-        assertThat(mWhiteList.isPackageWhiteListed("com.example")).isTrue();
-    }
-
-    @Test
-    public void isPackageWhiteListed_matchWithTwo() {
-        mCloudEpgFlags.setThirdPartyEpgInputCsv("com.example/.Foo,com.example/.Bar");
-        assertThat(mWhiteList.isPackageWhiteListed("com.example")).isTrue();
-    }
-
-    @Test
-    public void isPackageWhiteListed_matchBadInput() {
-        mCloudEpgFlags.setThirdPartyEpgInputCsv("com.example.Foo");
-        assertThat(mWhiteList.isPackageWhiteListed("com.example")).isFalse();
-    }
-
-    @Test
-    public void isPackageWhiteListed_tunerInput() {
-        EpgInputWhiteList whiteList =
-                new EpgInputWhiteList(new DefaultCloudEpgFlags(), DefaultLegacyFlags.DEFAULT);
-        assertThat(
-                        whiteList.isInputWhiteListed(
-                                "com.google.android.tv/.tuner.tvinput.TunerTvInputService"))
-                .isTrue();
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/dvr/BaseDvrDataManagerTest.java b/tests/robotests/src/com/android/tv/dvr/BaseDvrDataManagerTest.java
deleted file mode 100644
index 8c3baad..0000000
--- a/tests/robotests/src/com/android/tv/dvr/BaseDvrDataManagerTest.java
+++ /dev/null
@@ -1,96 +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.annotation.NonNull;
-
-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.TestSingletonApp;
-import com.android.tv.testing.dvr.DvrDataManagerInMemoryImpl;
-import com.android.tv.testing.dvr.RecordingTestUtils;
-import com.android.tv.testing.fakes.FakeClock;
-
-import com.google.common.truth.Truth;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-/** Tests for {@link BaseDvrDataManager} using {@link DvrDataManagerInMemoryImpl}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = Build.VERSION_CODES.N, application = TestSingletonApp.class)
-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;
-
-    @Before
-    public void setUp() {
-        mDvrFeature.enableForTest();
-        mFakeClock = FakeClock.createWithCurrentTime();
-        mDvrDataManager =
-                new DvrDataManagerInMemoryImpl(RuntimeEnvironment.application, mFakeClock);
-    }
-
-    @After
-    public void tearDown() {
-        mDvrFeature.resetForTests();
-    }
-
-    @Test
-    public void testGetNonStartedScheduledRecordings() {
-        ScheduledRecording recording =
-                mDvrDataManager.addScheduledRecordingInternal(
-                        createNewScheduledRecordingStartingNow());
-        List<ScheduledRecording> result = mDvrDataManager.getNonStartedScheduledRecordings();
-        Truth.assertThat(result).containsExactly(recording);
-    }
-
-    @Test
-    public void testGetNonStartedScheduledRecordings_past() {
-        mDvrDataManager.addScheduledRecordingInternal(createNewScheduledRecordingStartingNow());
-        mFakeClock.increment(TimeUnit.MINUTES, 6);
-        List<ScheduledRecording> result = mDvrDataManager.getNonStartedScheduledRecordings();
-        Truth.assertThat(result).isEmpty();
-    }
-
-    @NonNull
-    private ScheduledRecording createNewScheduledRecordingStartingNow() {
-        return ScheduledRecording.buildFrom(
-                        RecordingTestUtils.createTestRecordingWithIdAndPeriod(
-                                ScheduledRecording.ID_NOT_SET,
-                                INPUT_ID,
-                                CHANNEL_ID,
-                                mFakeClock.currentTimeMillis(),
-                                mFakeClock.currentTimeMillis() + TimeUnit.MINUTES.toMillis(5)))
-                .setState(ScheduledRecording.STATE_RECORDING_NOT_STARTED)
-                .build();
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/dvr/DvrDataManagerImplTest.java b/tests/robotests/src/com/android/tv/dvr/DvrDataManagerImplTest.java
deleted file mode 100644
index 528e023..0000000
--- a/tests/robotests/src/com/android/tv/dvr/DvrDataManagerImplTest.java
+++ /dev/null
@@ -1,85 +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 com.google.common.truth.Truth.assertWithMessage;
-
-import android.os.Build;
-
-import com.android.tv.dvr.data.ScheduledRecording;
-import com.android.tv.testing.TestSingletonApp;
-import com.android.tv.testing.dvr.RecordingTestUtils;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/** Tests for {@link DvrDataManagerImpl} */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = Build.VERSION_CODES.N, application = TestSingletonApp.class)
-public class DvrDataManagerImplTest {
-    private static final String INPUT_ID = "input_id";
-    private static final int CHANNEL_ID = 273;
-
-    @Test
-    public void testGetNextScheduledStartTimeAfter() {
-        long id = 1;
-        List<ScheduledRecording> scheduledRecordings = new ArrayList<>();
-        assertNextStartTime(scheduledRecordings, 0L, DvrDataManager.NEXT_START_TIME_NOT_FOUND);
-        scheduledRecordings.add(
-                RecordingTestUtils.createTestRecordingWithIdAndPeriod(
-                        id++, INPUT_ID, CHANNEL_ID, 10L, 20L));
-        assertNextStartTime(scheduledRecordings, 9L, 10L);
-        assertNextStartTime(scheduledRecordings, 10L, DvrDataManager.NEXT_START_TIME_NOT_FOUND);
-        scheduledRecordings.add(
-                RecordingTestUtils.createTestRecordingWithIdAndPeriod(
-                        id++, INPUT_ID, CHANNEL_ID, 20L, 30L));
-        assertNextStartTime(scheduledRecordings, 9L, 10L);
-        assertNextStartTime(scheduledRecordings, 10L, 20L);
-        assertNextStartTime(scheduledRecordings, 20L, DvrDataManager.NEXT_START_TIME_NOT_FOUND);
-        scheduledRecordings.add(
-                RecordingTestUtils.createTestRecordingWithIdAndPeriod(
-                        id++, INPUT_ID, CHANNEL_ID, 30L, 40L));
-        assertNextStartTime(scheduledRecordings, 9L, 10L);
-        assertNextStartTime(scheduledRecordings, 10L, 20L);
-        assertNextStartTime(scheduledRecordings, 20L, 30L);
-        assertNextStartTime(scheduledRecordings, 30L, DvrDataManager.NEXT_START_TIME_NOT_FOUND);
-        scheduledRecordings.clear();
-        scheduledRecordings.add(
-                RecordingTestUtils.createTestRecordingWithIdAndPeriod(
-                        id++, INPUT_ID, CHANNEL_ID, 10L, 20L));
-        scheduledRecordings.add(
-                RecordingTestUtils.createTestRecordingWithIdAndPeriod(
-                        id++, INPUT_ID, CHANNEL_ID, 10L, 20L));
-        scheduledRecordings.add(
-                RecordingTestUtils.createTestRecordingWithIdAndPeriod(
-                        id++, INPUT_ID, CHANNEL_ID, 10L, 20L));
-        assertNextStartTime(scheduledRecordings, 9L, 10L);
-        assertNextStartTime(scheduledRecordings, 10L, DvrDataManager.NEXT_START_TIME_NOT_FOUND);
-    }
-
-    private void assertNextStartTime(
-            List<ScheduledRecording> scheduledRecordings, long startTime, long expected) {
-        assertWithMessage("getNextScheduledStartTimeAfter()")
-                .that(DvrDataManagerImpl.getNextStartTimeAfter(scheduledRecordings, startTime))
-                .isEqualTo(expected);
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/dvr/DvrScheduleManagerTest.java b/tests/robotests/src/com/android/tv/dvr/DvrScheduleManagerTest.java
deleted file mode 100644
index bd4113e..0000000
--- a/tests/robotests/src/com/android/tv/dvr/DvrScheduleManagerTest.java
+++ /dev/null
@@ -1,883 +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 static com.google.common.truth.Truth.assertThat;
-
-import static org.junit.Assert.fail;
-
-import android.os.Build;
-import android.util.Range;
-
-import com.android.tv.dvr.DvrScheduleManager.ConflictInfo;
-import com.android.tv.dvr.data.ScheduledRecording;
-import com.android.tv.testing.TestSingletonApp;
-import com.android.tv.testing.dvr.RecordingTestUtils;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-/** Tests for {@link DvrScheduleManager} */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = Build.VERSION_CODES.N, application = TestSingletonApp.class)
-public class DvrScheduleManagerTest {
-    private static final String INPUT_ID = "input_id";
-
-    @Test
-    public void testGetConflictingSchedules_emptySchedule() {
-        List<ScheduledRecording> schedules = new ArrayList<>();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 1)).isEmpty();
-    }
-
-    @Test
-    public void testGetConflictingSchedules_noConflict() {
-        long priority = 0;
-        long channelId = 0;
-        List<ScheduledRecording> schedules = new ArrayList<>();
-
-        schedules.add(
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 0L, 200L));
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 1)).isEmpty();
-
-        schedules.add(
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 0L, 100L));
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 2)).isEmpty();
-
-        schedules.add(
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 100L, 200L));
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 2)).isEmpty();
-
-        schedules.add(
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 0L, 100L));
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 3)).isEmpty();
-
-        schedules.add(
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 100L, 200L));
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 3)).isEmpty();
-    }
-
-    @Test
-    public void testGetConflictingSchedules_noTuner() {
-        long priority = 0;
-        long channelId = 0;
-        List<ScheduledRecording> schedules = new ArrayList<>();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 0)).isEmpty();
-
-        schedules.add(
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 0L, 200L));
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 0)).isEqualTo(schedules);
-        schedules.add(
-                0,
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 0L, 100L));
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 0)).isEqualTo(schedules);
-    }
-
-    @Test
-    public void testGetConflictingSchedules_conflict() {
-        long priority = 0;
-        long channelId = 0;
-        List<ScheduledRecording> schedules = new ArrayList<>();
-
-        ScheduledRecording r1 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 0L, 200L);
-        schedules.add(r1);
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 1)).isEmpty();
-
-        ScheduledRecording r2 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 0L, 100L);
-        schedules.add(r2);
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 1))
-                .containsExactly(r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 2)).isEmpty();
-
-        ScheduledRecording r3 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 100L, 200L);
-        schedules.add(r3);
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 1))
-                .containsExactly(r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 2)).isEmpty();
-
-        ScheduledRecording r4 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 0L, 100L);
-        schedules.add(r4);
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 1))
-                .containsExactly(r2, r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 2))
-                .containsExactly(r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 3)).isEmpty();
-
-        ScheduledRecording r5 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 100L, 200L);
-        schedules.add(r5);
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 1))
-                .containsExactly(r3, r2, r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 2))
-                .containsExactly(r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 3)).isEmpty();
-
-        ScheduledRecording r6 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 10L, 90L);
-        schedules.add(r6);
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 1))
-                .containsExactly(r4, r3, r2, r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 2))
-                .containsExactly(r2, r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 3))
-                .containsExactly(r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 4)).isEmpty();
-
-        ScheduledRecording r7 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 110L, 190L);
-        schedules.add(r7);
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 1))
-                .containsExactly(r5, r4, r3, r2, r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 2))
-                .containsExactly(r3, r2, r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 3))
-                .containsExactly(r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 4)).isEmpty();
-
-        ScheduledRecording r8 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 50L, 150L);
-        schedules.add(r8);
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 1))
-                .containsExactly(r7, r6, r5, r4, r3, r2, r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 2))
-                .containsExactly(r5, r4, r3, r2, r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 3))
-                .containsExactly(r3, r2, r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 4))
-                .containsExactly(r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 5)).isEmpty();
-    }
-
-    @Test
-    public void testGetConflictingSchedules_conflict2() {
-        // The case when there is a long schedule.
-        long priority = 0;
-        long channelId = 0;
-        List<ScheduledRecording> schedules = new ArrayList<>();
-
-        ScheduledRecording r1 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 0L, 1000L);
-        schedules.add(r1);
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 1)).isEmpty();
-
-        ScheduledRecording r2 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 0L, 100L);
-        schedules.add(r2);
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 1))
-                .containsExactly(r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 2)).isEmpty();
-
-        ScheduledRecording r3 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 100L, 200L);
-        schedules.add(r3);
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 1))
-                .containsExactly(r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 2)).isEmpty();
-    }
-
-    @Test
-    public void testGetConflictingSchedules_reverseOrder() {
-        long priority = 0;
-        long channelId = 0;
-        List<ScheduledRecording> schedules = new ArrayList<>();
-
-        ScheduledRecording r1 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 0L, 200L);
-        schedules.add(0, r1);
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 1)).isEmpty();
-
-        ScheduledRecording r2 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 0L, 100L);
-        schedules.add(0, r2);
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 1))
-                .containsExactly(r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 2)).isEmpty();
-
-        ScheduledRecording r3 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 100L, 200L);
-        schedules.add(0, r3);
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 1))
-                .containsExactly(r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 2)).isEmpty();
-
-        ScheduledRecording r4 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 0L, 100L);
-        schedules.add(0, r4);
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 1))
-                .containsExactly(r2, r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 2))
-                .containsExactly(r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 3)).isEmpty();
-
-        ScheduledRecording r5 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 100L, 200L);
-        schedules.add(0, r5);
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 1))
-                .containsExactly(r3, r2, r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 2))
-                .containsExactly(r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 3)).isEmpty();
-
-        ScheduledRecording r6 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 10L, 90L);
-        schedules.add(0, r6);
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 1))
-                .containsExactly(r4, r3, r2, r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 2))
-                .containsExactly(r2, r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 3))
-                .containsExactly(r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 4)).isEmpty();
-
-        ScheduledRecording r7 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 110L, 190L);
-        schedules.add(0, r7);
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 1))
-                .containsExactly(r5, r4, r3, r2, r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 2))
-                .containsExactly(r3, r2, r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 3))
-                .containsExactly(r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 4)).isEmpty();
-
-        ScheduledRecording r8 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 50L, 150L);
-        schedules.add(0, r8);
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 1))
-                .containsExactly(r7, r6, r5, r4, r3, r2, r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 2))
-                .containsExactly(r5, r4, r3, r2, r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 3))
-                .containsExactly(r3, r2, r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 4))
-                .containsExactly(r1)
-                .inOrder();
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 5)).isEmpty();
-    }
-
-    @Test
-    public void testGetConflictingSchedules_period1() {
-        long priority = 0;
-        long channelId = 0;
-        List<ScheduledRecording> schedules = new ArrayList<>();
-
-        ScheduledRecording r1 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 0L, 200L);
-        schedules.add(r1);
-        ScheduledRecording r2 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 0L, 100L);
-        schedules.add(r2);
-        assertThat(
-                        DvrScheduleManager.getConflictingSchedules(
-                                schedules, 1, Collections.singletonList(new Range<>(10L, 20L))))
-                .containsExactly(r1)
-                .inOrder();
-        assertThat(
-                        DvrScheduleManager.getConflictingSchedules(
-                                schedules, 1, Collections.singletonList(new Range<>(110L, 120L))))
-                .containsExactly(r1)
-                .inOrder();
-    }
-
-    @Test
-    public void testGetConflictingSchedules_period2() {
-        long priority = 0;
-        long channelId = 0;
-        List<ScheduledRecording> schedules = new ArrayList<>();
-
-        ScheduledRecording r1 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 0L, 200L);
-        schedules.add(r1);
-        ScheduledRecording r2 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 100L, 200L);
-        schedules.add(r2);
-        assertThat(
-                        DvrScheduleManager.getConflictingSchedules(
-                                schedules, 1, Collections.singletonList(new Range<>(10L, 20L))))
-                .containsExactly(r1)
-                .inOrder();
-        assertThat(
-                        DvrScheduleManager.getConflictingSchedules(
-                                schedules, 1, Collections.singletonList(new Range<>(110L, 120L))))
-                .containsExactly(r1)
-                .inOrder();
-    }
-
-    @Test
-    public void testGetConflictingSchedules_period3() {
-        long priority = 0;
-        long channelId = 0;
-        List<ScheduledRecording> schedules = new ArrayList<>();
-
-        ScheduledRecording r1 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 0L, 100L);
-        schedules.add(r1);
-        ScheduledRecording r2 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 100L, 200L);
-        schedules.add(r2);
-        ScheduledRecording r3 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 0L, 100L);
-        schedules.add(r3);
-        ScheduledRecording r4 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 100L, 200L);
-        schedules.add(r4);
-        assertThat(
-                        DvrScheduleManager.getConflictingSchedules(
-                                schedules, 1, Collections.singletonList(new Range<>(10L, 20L))))
-                .containsExactly(r1)
-                .inOrder();
-        assertThat(
-                        DvrScheduleManager.getConflictingSchedules(
-                                schedules, 1, Collections.singletonList(new Range<>(110L, 120L))))
-                .containsExactly(r2)
-                .inOrder();
-        assertThat(
-                        DvrScheduleManager.getConflictingSchedules(
-                                schedules, 1, Collections.singletonList(new Range<>(50L, 150L))))
-                .containsExactly(r2, r1)
-                .inOrder();
-        List<Range<Long>> ranges = new ArrayList<>();
-        ranges.add(new Range<>(10L, 20L));
-        ranges.add(new Range<>(110L, 120L));
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 1, ranges))
-                .containsExactly(r2, r1)
-                .inOrder();
-    }
-
-    @Test
-    public void testGetConflictingSchedules_addSchedules1() {
-        long priority = 0;
-        long channelId = 0;
-        List<ScheduledRecording> schedules = new ArrayList<>();
-
-        ScheduledRecording r1 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 0L, 200L);
-        schedules.add(r1);
-        ScheduledRecording r2 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 0L, 100L);
-        schedules.add(r2);
-        assertThat(
-                        DvrScheduleManager.getConflictingSchedules(
-                                Collections.singletonList(
-                                        ScheduledRecording.builder(INPUT_ID, ++channelId, 10L, 20L)
-                                                .setPriority(++priority)
-                                                .build()),
-                                schedules,
-                                1))
-                .containsExactly(r2, r1)
-                .inOrder();
-        assertThat(
-                        DvrScheduleManager.getConflictingSchedules(
-                                Collections.singletonList(
-                                        ScheduledRecording.builder(
-                                                        INPUT_ID, ++channelId, 110L, 120L)
-                                                .setPriority(++priority)
-                                                .build()),
-                                schedules,
-                                1))
-                .containsExactly(r1)
-                .inOrder();
-    }
-
-    @Test
-    public void testGetConflictingSchedules_addSchedules2() {
-        long priority = 0;
-        long channelId = 0;
-        List<ScheduledRecording> schedules = new ArrayList<>();
-
-        ScheduledRecording r1 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 0L, 200L);
-        schedules.add(r1);
-        ScheduledRecording r2 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 100L, 200L);
-        schedules.add(r2);
-        assertThat(
-                        DvrScheduleManager.getConflictingSchedules(
-                                Collections.singletonList(
-                                        ScheduledRecording.builder(INPUT_ID, ++channelId, 10L, 20L)
-                                                .setPriority(++priority)
-                                                .build()),
-                                schedules,
-                                1))
-                .containsExactly(r1)
-                .inOrder();
-        assertThat(
-                        DvrScheduleManager.getConflictingSchedules(
-                                Collections.singletonList(
-                                        ScheduledRecording.builder(
-                                                        INPUT_ID, ++channelId, 110L, 120L)
-                                                .setPriority(++priority)
-                                                .build()),
-                                schedules,
-                                1))
-                .containsExactly(r2, r1)
-                .inOrder();
-    }
-
-    @Test
-    public void testGetConflictingSchedules_addLowestPriority() {
-        long priority = 0;
-        long channelId = 0;
-        List<ScheduledRecording> schedules = new ArrayList<>();
-
-        ScheduledRecording r1 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 0L, 400L);
-        schedules.add(r1);
-        ScheduledRecording r2 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 100L, 200L);
-        schedules.add(r2);
-        // Returning r1 even though r1 has the higher priority than the new one. That's because r1
-        // starts at 0 and stops at 100, and the new one will be recorded successfully.
-        assertThat(
-                        DvrScheduleManager.getConflictingSchedules(
-                                Collections.singletonList(
-                                        ScheduledRecording.builder(
-                                                        INPUT_ID, ++channelId, 200L, 300L)
-                                                .setPriority(0)
-                                                .build()),
-                                schedules,
-                                1))
-                .containsExactly(r1)
-                .inOrder();
-    }
-
-    @Test
-    public void testGetConflictingSchedules_sameChannel() {
-        long priority = 0;
-        long channelId = 1;
-        List<ScheduledRecording> schedules = new ArrayList<>();
-        schedules.add(
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        channelId, ++priority, 0L, 200L));
-        schedules.add(
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        channelId, ++priority, 0L, 200L));
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 3)).isEmpty();
-    }
-
-    @Test
-    public void testGetConflictingSchedule_startEarlyAndFail() {
-        long priority = 0;
-        long channelId = 0;
-        List<ScheduledRecording> schedules = new ArrayList<>();
-        ScheduledRecording r1 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 200L, 300L);
-        schedules.add(r1);
-        ScheduledRecording r2 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 0L, 400L);
-        schedules.add(r2);
-        ScheduledRecording r3 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 100L, 200L);
-        schedules.add(r3);
-        // r2 starts recording and fails when r3 starts. r1 is recorded successfully.
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 1))
-                .containsExactly(r2)
-                .inOrder();
-    }
-
-    @Test
-    public void testGetConflictingSchedule_startLate() {
-        long priority = 0;
-        long channelId = 0;
-        List<ScheduledRecording> schedules = new ArrayList<>();
-        ScheduledRecording r1 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 200L, 400L);
-        schedules.add(r1);
-        ScheduledRecording r2 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 100L, 300L);
-        schedules.add(r2);
-        ScheduledRecording r3 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 0L, 200L);
-        schedules.add(r3);
-        // r2 and r1 are clipped.
-        assertThat(DvrScheduleManager.getConflictingSchedules(schedules, 1))
-                .containsExactly(r2, r1)
-                .inOrder();
-    }
-
-    @Test
-    public void testGetConflictingSchedulesForTune_canTune() {
-        // Can tune to the recorded channel if tuner count is 1.
-        long priority = 0;
-        long channelId = 1;
-        List<ScheduledRecording> schedules = new ArrayList<>();
-        schedules.add(
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        channelId, ++priority, 0L, 200L));
-        assertThat(
-                        DvrScheduleManager.getConflictingSchedulesForTune(
-                                INPUT_ID, channelId, 0L, priority + 1, schedules, 1))
-                .isEmpty();
-    }
-
-    @Test
-    public void testGetConflictingSchedulesForTune_cannotTune() {
-        // Can't tune to a channel if other channel is recording and tuner count is 1.
-        long priority = 0;
-        long channelId = 1;
-        List<ScheduledRecording> schedules = new ArrayList<>();
-        schedules.add(
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        channelId, ++priority, 0L, 200L));
-        assertThat(
-                        DvrScheduleManager.getConflictingSchedulesForTune(
-                                INPUT_ID, channelId + 1, 0L, priority + 1, schedules, 1))
-                .containsExactly(schedules.get(0))
-                .inOrder();
-    }
-
-    @Test
-    public void testGetConflictingSchedulesForWatching_otherChannels() {
-        // The other channels are to be recorded.
-        long priority = 0;
-        long channelToWatch = 1;
-        long channelId = 1;
-        List<ScheduledRecording> schedules = new ArrayList<>();
-        ScheduledRecording r1 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 0L, 200L);
-        schedules.add(r1);
-        ScheduledRecording r2 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 0L, 200L);
-        schedules.add(r2);
-        assertThat(
-                        DvrScheduleManager.getConflictingSchedulesForWatching(
-                                INPUT_ID, channelToWatch, 0L, ++priority, schedules, 3))
-                .isEmpty();
-        assertThat(
-                        DvrScheduleManager.getConflictingSchedulesForWatching(
-                                INPUT_ID, channelToWatch, 0L, ++priority, schedules, 2))
-                .containsExactly(r1)
-                .inOrder();
-    }
-
-    @Test
-    public void testGetConflictingSchedulesForWatching_sameChannel1() {
-        long priority = 0;
-        long channelToWatch = 1;
-        long channelId = 1;
-        List<ScheduledRecording> schedules = new ArrayList<>();
-        ScheduledRecording r1 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        channelToWatch, ++priority, 0L, 200L);
-        schedules.add(r1);
-        ScheduledRecording r2 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 0L, 200L);
-        schedules.add(r2);
-        assertThat(
-                        DvrScheduleManager.getConflictingSchedulesForWatching(
-                                INPUT_ID, channelToWatch, 0L, ++priority, schedules, 2))
-                .isEmpty();
-        assertThat(
-                        DvrScheduleManager.getConflictingSchedulesForWatching(
-                                INPUT_ID, channelToWatch, 0L, ++priority, schedules, 1))
-                .containsExactly(r2)
-                .inOrder();
-    }
-
-    @Test
-    public void testGetConflictingSchedulesForWatching_sameChannel2() {
-        long priority = 0;
-        long channelToWatch = 1;
-        long channelId = 1;
-        List<ScheduledRecording> schedules = new ArrayList<>();
-        ScheduledRecording r1 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 0L, 200L);
-        schedules.add(r1);
-        ScheduledRecording r2 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        channelToWatch, ++priority, 0L, 200L);
-        schedules.add(r2);
-        assertThat(
-                        DvrScheduleManager.getConflictingSchedulesForWatching(
-                                INPUT_ID, channelToWatch, 0L, ++priority, schedules, 2))
-                .isEmpty();
-        assertThat(
-                        DvrScheduleManager.getConflictingSchedulesForWatching(
-                                INPUT_ID, channelToWatch, 0L, ++priority, schedules, 1))
-                .containsExactly(r1)
-                .inOrder();
-    }
-
-    @Test
-    public void testGetConflictingSchedulesForWatching_sameChannelConflict1() {
-        long priority = 0;
-        long channelToWatch = 1;
-        long channelId = 1;
-        List<ScheduledRecording> schedules = new ArrayList<>();
-        ScheduledRecording r1 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 0L, 200L);
-        schedules.add(r1);
-        ScheduledRecording r2 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        channelToWatch, ++priority, 0L, 200L);
-        schedules.add(r2);
-        ScheduledRecording r3 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        channelToWatch, ++priority, 0L, 200L);
-        schedules.add(r3);
-        assertThat(
-                        DvrScheduleManager.getConflictingSchedulesForWatching(
-                                INPUT_ID, channelToWatch, 0L, ++priority, schedules, 3))
-                .containsExactly(r2)
-                .inOrder();
-        assertThat(
-                        DvrScheduleManager.getConflictingSchedulesForWatching(
-                                INPUT_ID, channelToWatch, 0L, ++priority, schedules, 2))
-                .containsExactly(r2)
-                .inOrder();
-        assertThat(
-                        DvrScheduleManager.getConflictingSchedulesForWatching(
-                                INPUT_ID, channelToWatch, 0L, ++priority, schedules, 1))
-                .containsExactly(r2, r1)
-                .inOrder();
-    }
-
-    @Test
-    public void testGetConflictingSchedulesForWatching_sameChannelConflict2() {
-        long priority = 0;
-        long channelToWatch = 1;
-        long channelId = 1;
-        List<ScheduledRecording> schedules = new ArrayList<>();
-        ScheduledRecording r1 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        channelToWatch, ++priority, 0L, 200L);
-        schedules.add(r1);
-        ScheduledRecording r2 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        channelToWatch, ++priority, 0L, 200L);
-        schedules.add(r2);
-        ScheduledRecording r3 =
-                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                        ++channelId, ++priority, 0L, 200L);
-        schedules.add(r3);
-        assertThat(
-                        DvrScheduleManager.getConflictingSchedulesForWatching(
-                                INPUT_ID, channelToWatch, 0L, ++priority, schedules, 3))
-                .containsExactly(r1)
-                .inOrder();
-        assertThat(
-                        DvrScheduleManager.getConflictingSchedulesForWatching(
-                                INPUT_ID, channelToWatch, 0L, ++priority, schedules, 2))
-                .containsExactly(r1)
-                .inOrder();
-        assertThat(
-                        DvrScheduleManager.getConflictingSchedulesForWatching(
-                                INPUT_ID, channelToWatch, 0L, ++priority, schedules, 1))
-                .containsExactly(r3, r1)
-                .inOrder();
-    }
-
-    @Test
-    public void testPartiallyConflictingSchedules() {
-        long priority = 100;
-        long channelId = 0;
-        List<ScheduledRecording> schedules =
-                new ArrayList<>(
-                        Arrays.asList(
-                                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                                        ++channelId, --priority, 0L, 400L),
-                                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                                        ++channelId, --priority, 0L, 200L),
-                                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                                        ++channelId, --priority, 200L, 500L),
-                                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                                        ++channelId, --priority, 400L, 600L),
-                                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                                        ++channelId, --priority, 700L, 800L),
-                                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                                        ++channelId, --priority, 600L, 900L),
-                                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                                        ++channelId, --priority, 800L, 900L),
-                                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                                        ++channelId, --priority, 800L, 900L),
-                                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                                        ++channelId, --priority, 750L, 850L),
-                                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                                        ++channelId, --priority, 300L, 450L),
-                                RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(
-                                        ++channelId, --priority, 50L, 900L)));
-        List<ConflictInfo> conflicts = DvrScheduleManager.getConflictingSchedulesInfo(schedules, 1);
-
-        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);
-
-        conflicts = DvrScheduleManager.getConflictingSchedulesInfo(schedules, 2);
-
-        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);
-
-        conflicts = DvrScheduleManager.getConflictingSchedulesInfo(schedules, 3);
-
-        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");
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/dvr/ScheduledRecordingTest.java b/tests/robotests/src/com/android/tv/dvr/ScheduledRecordingTest.java
deleted file mode 100644
index 4c845c4..0000000
--- a/tests/robotests/src/com/android/tv/dvr/ScheduledRecordingTest.java
+++ /dev/null
@@ -1,126 +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 com.android.tv.testing.dvr.RecordingTestUtils.createTestRecordingWithIdAndPeriod;
-import static com.android.tv.testing.dvr.RecordingTestUtils.normalizePriority;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
-
-import android.os.Build;
-import android.util.Range;
-
-import com.android.tv.data.ChannelImpl;
-import com.android.tv.data.ProgramImpl;
-import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
-import com.android.tv.dvr.data.ScheduledRecording;
-import com.android.tv.testing.TestSingletonApp;
-import com.android.tv.testing.dvr.RecordingTestUtils;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-/** Tests for {@link ScheduledRecordingTest} */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = Build.VERSION_CODES.N, application = TestSingletonApp.class)
-public class ScheduledRecordingTest {
-    private static final String INPUT_ID = "input_id";
-    private static final int CHANNEL_ID = 273;
-
-    @Test
-    public void testIsOverLapping() {
-        ScheduledRecording r =
-                createTestRecordingWithIdAndPeriod(1, INPUT_ID, CHANNEL_ID, 10L, 20L);
-        assertOverLapping(false, 1L, 9L, r);
-
-        assertOverLapping(true, 1L, 20L, r);
-        assertOverLapping(false, 1L, 10L, r);
-        assertOverLapping(true, 10L, 19L, r);
-        assertOverLapping(true, 10L, 20L, r);
-        assertOverLapping(true, 11L, 20L, r);
-        assertOverLapping(true, 11L, 21L, r);
-        assertOverLapping(false, 20L, 21L, r);
-
-        assertOverLapping(false, 21L, 29L, r);
-    }
-
-    @Test
-    public void testBuildProgram() {
-        Channel c = new ChannelImpl.Builder().build();
-        Program p = new ProgramImpl.Builder().build();
-        ScheduledRecording actual =
-                ScheduledRecording.builder(INPUT_ID, p).setChannelId(c.getId()).build();
-        assertWithMessage("type").that(actual.getType()).isEqualTo(ScheduledRecording.TYPE_PROGRAM);
-    }
-
-    @Test
-    public void testBuildTime() {
-        ScheduledRecording actual =
-                createTestRecordingWithIdAndPeriod(1, INPUT_ID, CHANNEL_ID, 10L, 20L);
-        assertWithMessage("type").that(actual.getType()).isEqualTo(ScheduledRecording.TYPE_TIMED);
-    }
-
-    @Test
-    public void testBuildFrom() {
-        ScheduledRecording expected =
-                createTestRecordingWithIdAndPeriod(1, INPUT_ID, CHANNEL_ID, 10L, 20L);
-        ScheduledRecording actual = ScheduledRecording.buildFrom(expected).build();
-        RecordingTestUtils.assertRecordingEquals(expected, actual);
-    }
-
-    @Test
-    public void testBuild_priority() {
-        ScheduledRecording a =
-                normalizePriority(
-                        createTestRecordingWithIdAndPeriod(1, INPUT_ID, CHANNEL_ID, 10L, 20L));
-        ScheduledRecording b =
-                normalizePriority(
-                        createTestRecordingWithIdAndPeriod(2, INPUT_ID, CHANNEL_ID, 10L, 20L));
-        ScheduledRecording c =
-                normalizePriority(
-                        createTestRecordingWithIdAndPeriod(3, INPUT_ID, CHANNEL_ID, 10L, 20L));
-
-        // default priority
-        assertThat(sortByPriority(c, b, a)).containsExactly(a, b, c).inOrder();
-
-        // make A preferred over B
-        a = ScheduledRecording.buildFrom(a).setPriority(b.getPriority() + 2).build();
-        assertThat(sortByPriority(a, b, c)).containsExactly(b, c, a).inOrder();
-    }
-
-    public Collection<ScheduledRecording> sortByPriority(
-            ScheduledRecording a, ScheduledRecording b, ScheduledRecording c) {
-        List<ScheduledRecording> list = Arrays.asList(a, b, c);
-        Collections.sort(list, ScheduledRecording.PRIORITY_COMPARATOR);
-        return list;
-    }
-
-    private void assertOverLapping(boolean expected, long lower, long upper, ScheduledRecording r) {
-        assertWithMessage("isOverlapping(Range(" + lower + "," + upper + "), recording " + r)
-                .that(r.isOverLapping(new Range<>(lower, upper)))
-                .isEqualTo(expected);
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/dvr/data/SeriesRecordingTest.java b/tests/robotests/src/com/android/tv/dvr/data/SeriesRecordingTest.java
deleted file mode 100644
index a0b79ce..0000000
--- a/tests/robotests/src/com/android/tv/dvr/data/SeriesRecordingTest.java
+++ /dev/null
@@ -1,147 +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.data;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
-
-import android.os.Parcel;
-
-import com.android.tv.data.ProgramImpl;
-import com.android.tv.data.api.Program;
-import com.android.tv.testing.constants.ConfigConstants;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-/** Tests for {@link SeriesRecording}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-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;
-    private static final String SERIES_ID = "SERIES_ID";
-    private static final String OTHER_SERIES_ID = "OTHER_SERIES_ID";
-
-    private final SeriesRecording mBaseSeriesRecording =
-            new SeriesRecording.Builder()
-                    .setTitle(PROGRAM_TITLE)
-                    .setChannelId(CHANNEL_ID)
-                    .setSeriesId(SERIES_ID)
-                    .build();
-    private final SeriesRecording mSeriesRecordingSeason2 =
-            SeriesRecording.buildFrom(mBaseSeriesRecording).setStartFromSeason(2).build();
-    private final SeriesRecording mSeriesRecordingSeason2Episode5 =
-            SeriesRecording.buildFrom(mSeriesRecordingSeason2).setStartFromEpisode(5).build();
-    private final ProgramImpl mBaseProgram =
-            new ProgramImpl.Builder()
-                    .setTitle(PROGRAM_TITLE)
-                    .setChannelId(CHANNEL_ID)
-                    .setSeriesId(SERIES_ID)
-                    .build();
-
-    @Test
-    public void testParcelable() {
-        SeriesRecording r1 =
-                new SeriesRecording.Builder()
-                        .setId(1)
-                        .setChannelId(2)
-                        .setPriority(3)
-                        .setTitle("4")
-                        .setDescription("5")
-                        .setLongDescription("5-long")
-                        .setSeriesId("6")
-                        .setStartFromEpisode(7)
-                        .setStartFromSeason(8)
-                        .setChannelOption(SeriesRecording.OPTION_CHANNEL_ALL)
-                        .setCanonicalGenreIds(new int[] {9, 10})
-                        .setPosterUri("11")
-                        .setPhotoUri("12")
-                        .build();
-        Parcel p1 = Parcel.obtain();
-        Parcel p2 = Parcel.obtain();
-        try {
-            r1.writeToParcel(p1, 0);
-            byte[] bytes = p1.marshall();
-            p2.unmarshall(bytes, 0, bytes.length);
-            p2.setDataPosition(0);
-            SeriesRecording r2 = SeriesRecording.fromParcel(p2);
-            assertThat(r2).isEqualTo(r1);
-        } finally {
-            p1.recycle();
-            p2.recycle();
-        }
-    }
-
-    @Test
-    public void testDoesProgramMatch_simpleMatch() {
-        assertDoesProgramMatch(mBaseProgram, mBaseSeriesRecording, true);
-    }
-
-    @Test
-    public void testDoesProgramMatch_differentSeriesId() {
-        Program program =
-                new ProgramImpl.Builder(mBaseProgram).setSeriesId(OTHER_SERIES_ID).build();
-        assertDoesProgramMatch(program, mBaseSeriesRecording, false);
-    }
-
-    @Test
-    public void testDoesProgramMatch_differentChannel() {
-        Program program =
-                new ProgramImpl.Builder(mBaseProgram).setChannelId(OTHER_CHANNEL_ID).build();
-        assertDoesProgramMatch(program, mBaseSeriesRecording, false);
-    }
-
-    @Test
-    public void testDoesProgramMatch_startFromSeason2() {
-        ProgramImpl program = mBaseProgram;
-        assertDoesProgramMatch(program, mSeriesRecordingSeason2, true);
-        program = new ProgramImpl.Builder(program).setSeasonNumber("1").build();
-        assertDoesProgramMatch(program, mSeriesRecordingSeason2, false);
-        program = new ProgramImpl.Builder(program).setSeasonNumber("2").build();
-        assertDoesProgramMatch(program, mSeriesRecordingSeason2, true);
-        program = new ProgramImpl.Builder(program).setSeasonNumber("3").build();
-        assertDoesProgramMatch(program, mSeriesRecordingSeason2, true);
-    }
-
-    @Test
-    public void testDoesProgramMatch_startFromSeason2episode5() {
-        ProgramImpl program = mBaseProgram;
-        assertDoesProgramMatch(program, mSeriesRecordingSeason2Episode5, true);
-        program = new ProgramImpl.Builder(program).setSeasonNumber("2").build();
-        assertDoesProgramMatch(program, mSeriesRecordingSeason2Episode5, true);
-        program = new ProgramImpl.Builder(program).setEpisodeNumber("4").build();
-        assertDoesProgramMatch(program, mSeriesRecordingSeason2Episode5, false);
-        program = new ProgramImpl.Builder(program).setEpisodeNumber("5").build();
-        assertDoesProgramMatch(program, mSeriesRecordingSeason2Episode5, true);
-        program = new ProgramImpl.Builder(program).setEpisodeNumber("6").build();
-        assertDoesProgramMatch(program, mSeriesRecordingSeason2Episode5, true);
-        program =
-                new ProgramImpl.Builder(program).setSeasonNumber("3").setEpisodeNumber("1").build();
-        assertDoesProgramMatch(program, mSeriesRecordingSeason2Episode5, true);
-    }
-
-    private void assertDoesProgramMatch(
-            Program p, SeriesRecording seriesRecording, boolean expected) {
-        assertWithMessage(seriesRecording + " doesProgramMatch " + p)
-                .that(seriesRecording.matchProgram(p))
-                .isEqualTo(expected);
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/dvr/provider/DvrDbSyncTest.java b/tests/robotests/src/com/android/tv/dvr/provider/DvrDbSyncTest.java
deleted file mode 100644
index 5f8db0a..0000000
--- a/tests/robotests/src/com/android/tv/dvr/provider/DvrDbSyncTest.java
+++ /dev/null
@@ -1,178 +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.provider;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import com.android.tv.data.ChannelDataManager;
-import com.android.tv.data.ProgramImpl;
-import com.android.tv.data.api.Program;
-import com.android.tv.dvr.DvrManager;
-import com.android.tv.dvr.WritableDvrDataManager;
-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.testing.TestSingletonApp;
-import com.android.tv.testing.constants.ConfigConstants;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.android.util.concurrent.RoboExecutorService;
-import org.robolectric.annotation.Config;
-
-/** Tests for {@link com.android.tv.dvr.DvrScheduleManager} */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK, application = TestSingletonApp.class)
-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;
-    private static final long BASE_END_TIME_MS = 1;
-    private static final String BASE_SEASON_NUMBER = "2";
-    private static final String BASE_EPISODE_NUMBER = "3";
-    private ProgramImpl baseProgram;
-    private ProgramImpl baseSeriesProgram;
-    private ScheduledRecording baseSchedule;
-    private ScheduledRecording baseSeriesSchedule;
-
-    private DvrDbSync mDbSync;
-    @Mock private DvrManager mDvrManager;
-    @Mock private WritableDvrDataManager mDataManager;
-    @Mock private ChannelDataManager mChannelDataManager;
-    @Mock private SeriesRecordingScheduler mSeriesRecordingScheduler;
-
-    @Before
-    public void setUp() {
-        // TODO(b/69843199): make these static finals
-        baseProgram =
-                new ProgramImpl.Builder()
-                        .setId(BASE_PROGRAM_ID)
-                        .setStartTimeUtcMillis(BASE_START_TIME_MS)
-                        .setEndTimeUtcMillis(BASE_END_TIME_MS)
-                        .build();
-        baseSeriesProgram =
-                new ProgramImpl.Builder()
-                        .setId(BASE_PROGRAM_ID)
-                        .setStartTimeUtcMillis(BASE_START_TIME_MS)
-                        .setEndTimeUtcMillis(BASE_END_TIME_MS)
-                        .setSeasonNumber(BASE_SEASON_NUMBER)
-                        .setEpisodeNumber(BASE_EPISODE_NUMBER)
-                        .build();
-        baseSchedule = ScheduledRecording.builder(INPUT_ID, baseProgram).build();
-        baseSeriesSchedule = ScheduledRecording.builder(INPUT_ID, baseSeriesProgram).build();
-
-        MockitoAnnotations.initMocks(this);
-        when(mChannelDataManager.isDbLoadFinished()).thenReturn(true);
-        when(mDvrManager.addSeriesRecording(any(), any(), anyInt()))
-                .thenReturn(SeriesRecording.builder(INPUT_ID, baseProgram).build());
-        mDbSync =
-                new DvrDbSync(
-                        RuntimeEnvironment.application.getApplicationContext(),
-                        mDataManager,
-                        mChannelDataManager,
-                        mDvrManager,
-                        mSeriesRecordingScheduler,
-                        new RoboExecutorService());
-    }
-
-    @Test
-    public void testHandleUpdateProgram_null() {
-        addSchedule(BASE_PROGRAM_ID, baseSchedule);
-        mDbSync.handleUpdateProgram(null, BASE_PROGRAM_ID);
-        verify(mDataManager).removeScheduledRecording(baseSchedule);
-    }
-
-    @Test
-    public void testHandleUpdateProgram_changeTimeNotStarted() {
-        addSchedule(BASE_PROGRAM_ID, baseSchedule);
-        long startTimeMs = BASE_START_TIME_MS + 1;
-        long endTimeMs = BASE_END_TIME_MS + 1;
-        Program program =
-                new ProgramImpl.Builder(baseProgram)
-                        .setStartTimeUtcMillis(startTimeMs)
-                        .setEndTimeUtcMillis(endTimeMs)
-                        .build();
-        mDbSync.handleUpdateProgram(program, BASE_PROGRAM_ID);
-        assertUpdateScheduleCalled(program);
-    }
-
-    @Test
-    public void testHandleUpdateProgram_changeTimeInProgressNotCalled() {
-        addSchedule(
-                BASE_PROGRAM_ID,
-                ScheduledRecording.buildFrom(baseSchedule)
-                        .setState(ScheduledRecording.STATE_RECORDING_IN_PROGRESS)
-                        .build());
-        long startTimeMs = BASE_START_TIME_MS + 1;
-        Program program =
-                new ProgramImpl.Builder(baseProgram).setStartTimeUtcMillis(startTimeMs).build();
-        mDbSync.handleUpdateProgram(program, BASE_PROGRAM_ID);
-        verify(mDataManager, never()).updateScheduledRecording(any());
-    }
-
-    @Test
-    public void testHandleUpdateProgram_changeSeason() {
-        addSchedule(BASE_PROGRAM_ID, baseSeriesSchedule);
-        String seasonNumber = BASE_SEASON_NUMBER + "1";
-        String episodeNumber = BASE_EPISODE_NUMBER + "1";
-        Program program =
-                new ProgramImpl.Builder(baseSeriesProgram)
-                        .setSeasonNumber(seasonNumber)
-                        .setEpisodeNumber(episodeNumber)
-                        .build();
-        mDbSync.handleUpdateProgram(program, BASE_PROGRAM_ID);
-        assertUpdateScheduleCalled(program);
-    }
-
-    @Test
-    public void testHandleUpdateProgram_finished() {
-        addSchedule(
-                BASE_PROGRAM_ID,
-                ScheduledRecording.buildFrom(baseSeriesSchedule)
-                        .setState(ScheduledRecording.STATE_RECORDING_FINISHED)
-                        .build());
-        String seasonNumber = BASE_SEASON_NUMBER + "1";
-        String episodeNumber = BASE_EPISODE_NUMBER + "1";
-        Program program =
-                new ProgramImpl.Builder(baseSeriesProgram)
-                        .setSeasonNumber(seasonNumber)
-                        .setEpisodeNumber(episodeNumber)
-                        .build();
-        mDbSync.handleUpdateProgram(program, BASE_PROGRAM_ID);
-        verify(mDataManager, never()).updateScheduledRecording(any());
-    }
-
-    private void addSchedule(long programId, ScheduledRecording schedule) {
-        when(mDataManager.getScheduledRecordingForProgramId(programId)).thenReturn(schedule);
-    }
-
-    private void assertUpdateScheduleCalled(Program program) {
-        verify(mDataManager)
-                .updateScheduledRecording(
-                        eq(ScheduledRecording.builder(INPUT_ID, program).build()));
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/dvr/provider/EpisodicProgramLoadTaskTest.java b/tests/robotests/src/com/android/tv/dvr/provider/EpisodicProgramLoadTaskTest.java
deleted file mode 100644
index 3597342..0000000
--- a/tests/robotests/src/com/android/tv/dvr/provider/EpisodicProgramLoadTaskTest.java
+++ /dev/null
@@ -1,92 +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.provider;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.os.Build.VERSION_CODES;
-
-import com.android.tv.dvr.data.SeasonEpisodeNumber;
-import com.android.tv.testing.TestSingletonApp;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/** Tests for {@link EpisodicProgramLoadTask} */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = VERSION_CODES.N, application = TestSingletonApp.class)
-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);
-        assertThat(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);
-        assertThat(seasonEpisodeNumbers)
-                .doesNotContain(
-                        new SeasonEpisodeNumber(
-                                SERIES_RECORDING_ID2, SEASON_NUMBER1, EPISODE_NUMBER1));
-        assertThat(seasonEpisodeNumbers)
-                .doesNotContain(
-                        new SeasonEpisodeNumber(
-                                SERIES_RECORDING_ID1, SEASON_NUMBER2, EPISODE_NUMBER1));
-        assertThat(seasonEpisodeNumbers)
-                .doesNotContain(
-                        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);
-        assertThat(seasonEpisodeNumbers)
-                .doesNotContain(
-                        new SeasonEpisodeNumber(SERIES_RECORDING_ID1, null, EPISODE_NUMBER1));
-        assertThat(seasonEpisodeNumbers)
-                .doesNotContain(
-                        new SeasonEpisodeNumber(SERIES_RECORDING_ID1, SEASON_NUMBER1, null));
-        assertThat(seasonEpisodeNumbers)
-                .doesNotContain(new SeasonEpisodeNumber(SERIES_RECORDING_ID1, null, null));
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/dvr/recorder/InputTaskSchedulerTest.java b/tests/robotests/src/com/android/tv/dvr/recorder/InputTaskSchedulerTest.java
deleted file mode 100644
index 40069f6..0000000
--- a/tests/robotests/src/com/android/tv/dvr/recorder/InputTaskSchedulerTest.java
+++ /dev/null
@@ -1,259 +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.recorder;
-
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyLong;
-import static org.mockito.Matchers.eq;
-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;
-
-import android.app.AlarmManager;
-import android.media.tv.TvInputInfo;
-import android.os.Build;
-import android.os.Looper;
-import android.os.SystemClock;
-
-import com.android.tv.InputSessionManager;
-import com.android.tv.common.util.Clock;
-import com.android.tv.data.ChannelDataManager;
-import com.android.tv.data.api.Channel;
-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.TestSingletonApp;
-import com.android.tv.testing.dvr.RecordingTestUtils;
-import com.android.tv.testing.fakes.FakeClock;
-import com.android.tv.testing.utils.TestUtils;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-/** Tests for {@link InputTaskScheduler}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = Build.VERSION_CODES.N, application = TestSingletonApp.class)
-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);
-    private static final int TUNER_COUNT_ONE = 1;
-    private static final int TUNER_COUNT_TWO = 2;
-    private static final long LOW_PRIORITY = 1;
-    private static final long HIGH_PRIORITY = 2;
-
-    private FakeClock mFakeClock;
-    private InputTaskScheduler mScheduler;
-    @Mock private DvrManager mDvrManager;
-    @Mock private WritableDvrDataManager mDataManager;
-    @Mock private InputSessionManager mSessionManager;
-    @Mock private AlarmManager mMockAlarmManager;
-    @Mock private ChannelDataManager mChannelDataManager;
-    private List<RecordingTask> mRecordingTasks;
-
-    @Before
-    public void setUp() throws Exception {
-        if (Looper.myLooper() == null) {
-            Looper.prepare();
-        }
-        mRecordingTasks = new ArrayList();
-        MockitoAnnotations.initMocks(this);
-        mFakeClock = FakeClock.createWithCurrentTime();
-        TvInputInfo input = createTvInputInfo(TUNER_COUNT_ONE);
-        mScheduler =
-                new InputTaskScheduler(
-                        RuntimeEnvironment.application,
-                        input,
-                        Looper.myLooper(),
-                        mChannelDataManager,
-                        mDvrManager,
-                        mDataManager,
-                        mSessionManager,
-                        mFakeClock,
-                        new RecordingTaskFactory() {
-                            @Override
-                            public RecordingTask createRecordingTask(
-                                    ScheduledRecording scheduledRecording,
-                                    Channel channel,
-                                    DvrManager dvrManager,
-                                    InputSessionManager sessionManager,
-                                    WritableDvrDataManager dataManager,
-                                    Clock clock) {
-                                RecordingTask task = mock(RecordingTask.class);
-                                when(task.getPriority())
-                                        .thenReturn(scheduledRecording.getPriority());
-                                when(task.getEndTimeMs())
-                                        .thenReturn(scheduledRecording.getEndTimeMs());
-                                mRecordingTasks.add(task);
-                                return task;
-                            }
-                        });
-    }
-
-    @Test
-    public void testAddSchedule_past() {
-        ScheduledRecording r =
-                RecordingTestUtils.createTestRecordingWithPeriod(INPUT_ID, CHANNEL_ID, 0L, 1L);
-        when(mDataManager.getScheduledRecording(anyLong())).thenReturn(r);
-        mScheduler.handleAddSchedule(r);
-        mScheduler.handleBuildSchedule();
-        verify(mDataManager, timeout((int) LISTENER_TIMEOUT_MS).times(1))
-                .changeState(
-                        any(ScheduledRecording.class),
-                        eq(ScheduledRecording.STATE_RECORDING_FAILED),
-                        eq(
-                                ScheduledRecording
-                                        .FAILED_REASON_PROGRAM_ENDED_BEFORE_RECORDING_STARTED));
-    }
-
-    @Test
-    public void testAddSchedule_start() {
-        mScheduler.handleAddSchedule(
-                RecordingTestUtils.createTestRecordingWithPeriod(
-                        INPUT_ID,
-                        CHANNEL_ID,
-                        mFakeClock.currentTimeMillis(),
-                        mFakeClock.currentTimeMillis() + TimeUnit.HOURS.toMillis(1)));
-        mScheduler.handleBuildSchedule();
-        verify(mRecordingTasks.get(0), timeout((int) LISTENER_TIMEOUT_MS).times(1)).start();
-    }
-
-    @Test
-    public void testAddSchedule_consecutiveNoStop() {
-        long startTimeMs = mFakeClock.currentTimeMillis();
-        long endTimeMs = startTimeMs + TimeUnit.SECONDS.toMillis(1);
-        long id = 0;
-        mScheduler.handleAddSchedule(
-                RecordingTestUtils.createTestRecordingWithIdAndPriorityAndPeriod(
-                        ++id, CHANNEL_ID, LOW_PRIORITY, startTimeMs, endTimeMs));
-        mScheduler.handleBuildSchedule();
-        startTimeMs = endTimeMs;
-        endTimeMs = startTimeMs + TimeUnit.SECONDS.toMillis(1);
-        mScheduler.handleAddSchedule(
-                RecordingTestUtils.createTestRecordingWithIdAndPriorityAndPeriod(
-                        ++id, CHANNEL_ID, HIGH_PRIORITY, startTimeMs, endTimeMs));
-        mScheduler.handleBuildSchedule();
-        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.
-        SystemClock.sleep(LISTENER_TIMEOUT_MS);
-        verify(mRecordingTasks.get(0), never()).stop();
-    }
-
-    @Test
-    public void testAddSchedule_consecutiveNoFail() {
-        long startTimeMs = mFakeClock.currentTimeMillis();
-        long endTimeMs = startTimeMs + TimeUnit.SECONDS.toMillis(1);
-        long id = 0;
-        when(mDataManager.getScheduledRecording(anyLong()))
-                .thenReturn(ScheduledRecording.builder(INPUT_ID, CHANNEL_ID, 0L, 0L).build());
-        mScheduler.handleAddSchedule(
-                RecordingTestUtils.createTestRecordingWithIdAndPriorityAndPeriod(
-                        ++id, CHANNEL_ID, HIGH_PRIORITY, startTimeMs, endTimeMs));
-        mScheduler.handleBuildSchedule();
-        startTimeMs = endTimeMs;
-        endTimeMs = startTimeMs + TimeUnit.SECONDS.toMillis(1);
-        mScheduler.handleAddSchedule(
-                RecordingTestUtils.createTestRecordingWithIdAndPriorityAndPeriod(
-                        ++id, CHANNEL_ID, LOW_PRIORITY, startTimeMs, endTimeMs));
-        mScheduler.handleBuildSchedule();
-        verify(mRecordingTasks.get(0), timeout((int) LISTENER_TIMEOUT_MS).times(1)).start();
-        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.
-        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);
-        long startTimeMs = mFakeClock.currentTimeMillis();
-        long endTimeMs = startTimeMs + TimeUnit.SECONDS.toMillis(1);
-        long id = 0;
-        mScheduler.handleAddSchedule(
-                RecordingTestUtils.createTestRecordingWithIdAndPriorityAndPeriod(
-                        ++id, CHANNEL_ID, LOW_PRIORITY, startTimeMs, endTimeMs));
-        mScheduler.handleBuildSchedule();
-        startTimeMs = endTimeMs;
-        endTimeMs = startTimeMs + TimeUnit.SECONDS.toMillis(1);
-        mScheduler.handleAddSchedule(
-                RecordingTestUtils.createTestRecordingWithIdAndPriorityAndPeriod(
-                        ++id, CHANNEL_ID, HIGH_PRIORITY, startTimeMs, endTimeMs));
-        mScheduler.handleBuildSchedule();
-        verify(mRecordingTasks.get(0), timeout((int) LISTENER_TIMEOUT_MS).times(1)).start();
-        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);
-    }
-
-    @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);
-        SystemClock.sleep(LISTENER_TIMEOUT_MS);
-        verify(mRecordingTasks.get(0), never()).cancel();
-    }
-
-    @Test
-    public void testUpdateSchedule_cancel() {
-        ScheduledRecording r =
-                RecordingTestUtils.createTestRecordingWithPeriod(
-                        INPUT_ID,
-                        CHANNEL_ID,
-                        mFakeClock.currentTimeMillis(),
-                        mFakeClock.currentTimeMillis() + TimeUnit.HOURS.toMillis(2));
-        mScheduler.handleAddSchedule(r);
-        mScheduler.handleBuildSchedule();
-        mScheduler.handleUpdateSchedule(
-                ScheduledRecording.buildFrom(r)
-                        .setStartTimeMs(mFakeClock.currentTimeMillis() + TimeUnit.HOURS.toMillis(1))
-                        .build());
-        verify(mRecordingTasks.get(0), timeout((int) LISTENER_TIMEOUT_MS).times(1)).cancel();
-    }
-
-    private TvInputInfo createTvInputInfo(int tunerCount) throws Exception {
-        return TestUtils.createTvInputInfo(null, null, null, 0, false, true, tunerCount);
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/dvr/recorder/RecordingTaskTest.java b/tests/robotests/src/com/android/tv/dvr/recorder/RecordingTaskTest.java
deleted file mode 100644
index 55ee270..0000000
--- a/tests/robotests/src/com/android/tv/dvr/recorder/RecordingTaskTest.java
+++ /dev/null
@@ -1,164 +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.recorder;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyLong;
-import static org.mockito.ArgumentMatchers.anyString;
-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 android.os.Build;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-
-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.ChannelImpl;
-import com.android.tv.data.api.Channel;
-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.TestSingletonApp;
-import com.android.tv.testing.dvr.DvrDataManagerInMemoryImpl;
-import com.android.tv.testing.dvr.RecordingTestUtils;
-import com.android.tv.testing.fakes.FakeClock;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-import java.util.concurrent.TimeUnit;
-
-/** Tests for {@link RecordingTask}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = Build.VERSION_CODES.N, application = TestSingletonApp.class)
-public class RecordingTaskTest {
-    private static final long DURATION = TimeUnit.MINUTES.toMillis(30);
-    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;
-
-    private FakeClock mFakeClock;
-    private DvrDataManagerInMemoryImpl mDataManager;
-    @Mock Handler mMockHandler;
-    @Mock DvrManager mDvrManager;
-    @Mock InputSessionManager mMockSessionManager;
-    @Mock RecordingSession mMockRecordingSession;
-    private final TestableFeature mDvrFeature = CommonFeatures.DVR;
-
-    @Before
-    public void setUp() {
-        mDvrFeature.enableForTest();
-        if (Looper.myLooper() == null) {
-            Looper.prepare();
-        }
-        MockitoAnnotations.initMocks(this);
-        mFakeClock = FakeClock.createWithCurrentTime();
-        mDataManager = new DvrDataManagerInMemoryImpl(RuntimeEnvironment.application, mFakeClock);
-    }
-
-    @After
-    public void tearDown() {
-        mDvrFeature.resetForTests();
-    }
-
-    @Test
-    public void testHandle_init() {
-        Channel channel = createTestChannel();
-        ScheduledRecording r = createRecording(channel);
-        RecordingTask task = createRecordingTask(r, channel);
-        String inputId = channel.getInputId();
-        when(mMockSessionManager.createRecordingSession(
-                        eq(inputId), anyString(), eq(task), eq(mMockHandler), anyLong()))
-                .thenReturn(mMockRecordingSession);
-        when(mMockHandler.sendMessageAtTime(any(), anyLong())).thenReturn(true);
-        assertTrue(task.handleMessage(createMessage(RecordingTask.MSG_INITIALIZE)));
-        assertEquals(State.CONNECTION_PENDING, task.getState());
-        verify(mMockSessionManager)
-                .createRecordingSession(
-                        eq(inputId), anyString(), eq(task), eq(mMockHandler), anyLong());
-        verify(mMockRecordingSession).tune(eq(inputId), eq(channel.getUri()));
-        verifyNoMoreInteractions(mMockHandler, mMockRecordingSession, mMockSessionManager);
-    }
-
-    private static Channel createTestChannel() {
-        return new ChannelImpl.Builder()
-                .setInputId(INPUT_ID)
-                .setId(CHANNEL_ID)
-                .setDisplayName("Test Ch " + CHANNEL_ID)
-                .build();
-    }
-
-    @Test
-    public void testOnConnected() {
-        Channel channel = createTestChannel();
-        ScheduledRecording r = createRecording(channel);
-        mDataManager.addScheduledRecording(r);
-        RecordingTask task = createRecordingTask(r, channel);
-        String inputId = channel.getInputId();
-        when(mMockSessionManager.createRecordingSession(
-                        eq(inputId), anyString(), eq(task), eq(mMockHandler), anyLong()))
-                .thenReturn(mMockRecordingSession);
-        when(mMockHandler.sendEmptyMessageDelayed(anyInt(), anyLong())).thenReturn(true);
-        task.handleMessage(createMessage(RecordingTask.MSG_INITIALIZE));
-        task.onTuned(channel.getUri());
-        assertEquals(State.CONNECTED, task.getState());
-    }
-
-    private ScheduledRecording createRecording(Channel c) {
-        long startTime = mFakeClock.currentTimeMillis() + START_OFFSET_MS;
-        long endTime = startTime + DURATION;
-        return RecordingTestUtils.createTestRecordingWithPeriod(
-                c.getInputId(), c.getId(), startTime, endTime);
-    }
-
-    private RecordingTask createRecordingTask(ScheduledRecording r, Channel channel) {
-        RecordingTask recordingTask =
-                new RecordingTask(
-                        RuntimeEnvironment.application,
-                        r,
-                        channel,
-                        mDvrManager,
-                        mMockSessionManager,
-                        mDataManager,
-                        mFakeClock);
-        recordingTask.setHandler(mMockHandler);
-        return recordingTask;
-    }
-
-    private Message createMessage(int what) {
-        Message msg = new Message();
-        msg.setTarget(mMockHandler);
-        msg.what = what;
-        return msg;
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/dvr/recorder/ScheduledProgramReaperTest.java b/tests/robotests/src/com/android/tv/dvr/recorder/ScheduledProgramReaperTest.java
deleted file mode 100644
index 945c031..0000000
--- a/tests/robotests/src/com/android/tv/dvr/recorder/ScheduledProgramReaperTest.java
+++ /dev/null
@@ -1,136 +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.recorder;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.junit.Assert.assertTrue;
-
-import android.os.Build;
-
-import com.android.tv.common.feature.CommonFeatures;
-import com.android.tv.common.feature.TestableFeature;
-import com.android.tv.common.util.CommonUtils;
-import com.android.tv.dvr.DvrManager;
-import com.android.tv.dvr.data.ScheduledRecording;
-import com.android.tv.testing.TestSingletonApp;
-import com.android.tv.testing.dvr.DvrDataManagerInMemoryImpl;
-import com.android.tv.testing.dvr.RecordingTestUtils;
-import com.android.tv.testing.fakes.FakeClock;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-import java.util.concurrent.TimeUnit;
-
-/** Tests for {@link ScheduledProgramReaper}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = Build.VERSION_CODES.N, application = TestSingletonApp.class)
-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);
-
-    private ScheduledProgramReaper mReaper;
-    private FakeClock mFakeClock;
-    private DvrDataManagerInMemoryImpl mDvrDataManager;
-    @Mock private DvrManager mDvrManager;
-    private final TestableFeature mDvrFeature = CommonFeatures.DVR;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mDvrFeature.enableForTest();
-        mFakeClock = FakeClock.createWithTimeOne();
-        mDvrDataManager =
-                new DvrDataManagerInMemoryImpl(RuntimeEnvironment.application, mFakeClock);
-        mReaper = new ScheduledProgramReaper(mDvrDataManager, mFakeClock);
-    }
-
-    @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();
-        assertThat(mDvrDataManager.getAllScheduledRecordings()).containsExactly(recording);
-        mReaper.run();
-        assertThat(mDvrDataManager.getAllScheduledRecordings()).containsExactly(recording);
-    }
-
-    @Test
-    public void testRun_oneRecordingsStarted() {
-        ScheduledRecording recording = addNewScheduledRecordingForTomorrow();
-        assertThat(mDvrDataManager.getAllScheduledRecordings()).containsExactly(recording);
-        mFakeClock.increment(TimeUnit.DAYS);
-        mReaper.run();
-        assertThat(mDvrDataManager.getAllScheduledRecordings()).containsExactly(recording);
-    }
-
-    @Test
-    public void testRun_oneRecordingsFinished() {
-        ScheduledRecording recording = addNewScheduledRecordingForTomorrow();
-        assertThat(mDvrDataManager.getAllScheduledRecordings()).containsExactly(recording);
-        mFakeClock.increment(TimeUnit.DAYS);
-        mFakeClock.increment(TimeUnit.MINUTES, 2);
-        mReaper.run();
-        assertThat(mDvrDataManager.getAllScheduledRecordings()).containsExactly(recording);
-    }
-
-    @Test
-    public void testRun_oneRecordingsExpired() {
-        ScheduledRecording recording = addNewScheduledRecordingForTomorrow();
-        assertThat(mDvrDataManager.getAllScheduledRecordings()).containsExactly(recording);
-        mFakeClock.increment(TimeUnit.DAYS, 1 + ScheduledProgramReaper.DAYS);
-        mFakeClock.increment(TimeUnit.MILLISECONDS, DURATION);
-        // After the cutoff and enough so we can see on the clock
-        mFakeClock.increment(TimeUnit.SECONDS, 1);
-
-        mReaper.run();
-        assertTrue(
-                "Recordings after reaper at "
-                        + CommonUtils.toIsoDateTimeString(mFakeClock.currentTimeMillis()),
-                mDvrDataManager.getAllScheduledRecordings().isEmpty());
-    }
-
-    private ScheduledRecording addNewScheduledRecordingForTomorrow() {
-        long startTime = mFakeClock.currentTimeMillis() + TimeUnit.DAYS.toMillis(1);
-        ScheduledRecording recording =
-                RecordingTestUtils.createTestRecordingWithPeriod(
-                        INPUT_ID, CHANNEL_ID, startTime, startTime + DURATION);
-        return mDvrDataManager.addScheduledRecordingInternal(
-                ScheduledRecording.buildFrom(recording)
-                        .setState(ScheduledRecording.STATE_RECORDING_FINISHED)
-                        .build());
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/dvr/recorder/SchedulerTest.java b/tests/robotests/src/com/android/tv/dvr/recorder/SchedulerTest.java
deleted file mode 100644
index d2bd2ff..0000000
--- a/tests/robotests/src/com/android/tv/dvr/recorder/SchedulerTest.java
+++ /dev/null
@@ -1,136 +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.recorder;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
-
-import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.os.Build;
-import android.os.Looper;
-
-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.DvrManager;
-import com.android.tv.dvr.data.ScheduledRecording;
-import com.android.tv.testing.TestSingletonApp;
-import com.android.tv.testing.dvr.DvrDataManagerInMemoryImpl;
-import com.android.tv.testing.dvr.RecordingTestUtils;
-import com.android.tv.testing.fakes.FakeClock;
-import com.android.tv.util.TvInputManagerHelper;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-import java.util.concurrent.TimeUnit;
-
-/** Tests for {@link RecordingScheduler}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = Build.VERSION_CODES.N, application = TestSingletonApp.class)
-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 RecordingScheduler mScheduler;
-    @Mock DvrManager mDvrManager;
-    @Mock InputSessionManager mSessionManager;
-    @Mock AlarmManager mMockAlarmManager;
-    @Mock ChannelDataManager mChannelDataManager;
-    @Mock TvInputManagerHelper mInputManager;
-    private final TestableFeature mDvrFeature = CommonFeatures.DVR;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mDvrFeature.enableForTest();
-        mFakeClock = FakeClock.createWithCurrentTime();
-        mDataManager = new DvrDataManagerInMemoryImpl(RuntimeEnvironment.application, mFakeClock);
-        Mockito.when(mChannelDataManager.isDbLoadFinished()).thenReturn(true);
-        mScheduler =
-                new RecordingScheduler(
-                        Looper.myLooper(),
-                        mDvrManager,
-                        mSessionManager,
-                        mDataManager,
-                        mChannelDataManager,
-                        mInputManager,
-                        RuntimeEnvironment.application,
-                        mFakeClock,
-                        mMockAlarmManager);
-    }
-
-    @After
-    public void tearDown() {
-        mDvrFeature.resetForTests();
-    }
-
-    @Test
-    public void testUpdate_none() {
-        mScheduler.updateAndStartServiceIfNeeded();
-        verifyZeroInteractions(mMockAlarmManager);
-    }
-
-    @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);
-        verify(mMockAlarmManager)
-                .setExactAndAllowWhileIdle(
-                        eq(AlarmManager.RTC_WAKEUP),
-                        eq(startTime - RecordingScheduler.MS_TO_WAKE_BEFORE_START),
-                        any(PendingIntent.class));
-        Mockito.reset(mMockAlarmManager);
-        mScheduler.updateAndStartServiceIfNeeded();
-        verify(mMockAlarmManager)
-                .setExactAndAllowWhileIdle(
-                        eq(AlarmManager.RTC_WAKEUP),
-                        eq(startTime - RecordingScheduler.MS_TO_WAKE_BEFORE_START),
-                        any(PendingIntent.class));
-    }
-
-    @Test
-    public void testStartsWithin() {
-        long now = mFakeClock.currentTimeMillis();
-        long startTime = now + 3;
-        ScheduledRecording r =
-                RecordingTestUtils.createTestRecordingWithPeriod(
-                        INPUT_ID, CHANNEL_ID, startTime, startTime + 100);
-        assertFalse(mScheduler.startsWithin(r, 2));
-        assertTrue(mScheduler.startsWithin(r, 3));
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/dvr/recorder/SeriesRecordingSchedulerTest.java b/tests/robotests/src/com/android/tv/dvr/recorder/SeriesRecordingSchedulerTest.java
deleted file mode 100644
index dc4f4db..0000000
--- a/tests/robotests/src/com/android/tv/dvr/recorder/SeriesRecordingSchedulerTest.java
+++ /dev/null
@@ -1,154 +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.recorder;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.os.Build;
-import android.util.LongSparseArray;
-
-import com.android.tv.common.feature.CommonFeatures;
-import com.android.tv.common.feature.TestableFeature;
-import com.android.tv.data.ProgramImpl;
-import com.android.tv.data.api.Program;
-import com.android.tv.dvr.data.SeriesRecording;
-import com.android.tv.testing.TestSingletonApp;
-import com.android.tv.testing.dvr.DvrDataManagerInMemoryImpl;
-import com.android.tv.testing.fakes.FakeClock;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/** Tests for {@link SeriesRecordingScheduler} */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = Build.VERSION_CODES.N, application = TestSingletonApp.class)
-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;
-    private static final String SERIES_ID = "SERIES_ID";
-    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";
-
-    private final SeriesRecording mBaseSeriesRecording =
-            new SeriesRecording.Builder()
-                    .setTitle(PROGRAM_TITLE)
-                    .setChannelId(CHANNEL_ID)
-                    .setSeriesId(SERIES_ID)
-                    .build();
-    private final ProgramImpl mBaseProgram =
-            new ProgramImpl.Builder()
-                    .setTitle(PROGRAM_TITLE)
-                    .setChannelId(CHANNEL_ID)
-                    .setSeriesId(SERIES_ID)
-                    .build();
-    private final TestableFeature mDvrFeature = CommonFeatures.DVR;
-
-    private DvrDataManagerInMemoryImpl mDataManager;
-
-    @Before
-    public void setUp() {
-        mDvrFeature.enableForTest();
-        FakeClock fakeClock = FakeClock.createWithCurrentTime();
-        mDataManager = new DvrDataManagerInMemoryImpl(RuntimeEnvironment.application, fakeClock);
-    }
-
-    @After
-    public void tearDown() {
-        mDvrFeature.resetForTests();
-    }
-
-    @Test
-    public void testPickOneProgramPerEpisode_onePerEpisode() {
-        SeriesRecording seriesRecording =
-                SeriesRecording.buildFrom(mBaseSeriesRecording).setId(SERIES_RECORDING_ID1).build();
-        mDataManager.addSeriesRecording(seriesRecording);
-        List<Program> programs = new ArrayList<>();
-        Program program1 =
-                new ProgramImpl.Builder(mBaseProgram)
-                        .setSeasonNumber(SEASON_NUMBER1)
-                        .setEpisodeNumber(EPISODE_NUMBER1)
-                        .build();
-        programs.add(program1);
-        Program program2 =
-                new ProgramImpl.Builder(mBaseProgram)
-                        .setSeasonNumber(SEASON_NUMBER2)
-                        .setEpisodeNumber(EPISODE_NUMBER2)
-                        .build();
-        programs.add(program2);
-        LongSparseArray<List<Program>> result =
-                SeriesRecordingScheduler.pickOneProgramPerEpisode(
-                        mDataManager, Collections.singletonList(seriesRecording), programs);
-        assertThat(result.get(SERIES_RECORDING_ID1)).containsExactly(program1, program2);
-    }
-
-    @Test
-    public void testPickOneProgramPerEpisode_manyPerEpisode() {
-        SeriesRecording seriesRecording =
-                SeriesRecording.buildFrom(mBaseSeriesRecording).setId(SERIES_RECORDING_ID1).build();
-        mDataManager.addSeriesRecording(seriesRecording);
-        List<Program> programs = new ArrayList<>();
-        ProgramImpl program1 =
-                new ProgramImpl.Builder(mBaseProgram)
-                        .setSeasonNumber(SEASON_NUMBER1)
-                        .setEpisodeNumber(EPISODE_NUMBER1)
-                        .setStartTimeUtcMillis(0)
-                        .build();
-        programs.add(program1);
-        Program program2 = new ProgramImpl.Builder(program1).setStartTimeUtcMillis(1).build();
-        programs.add(program2);
-        Program program3 =
-                new ProgramImpl.Builder(mBaseProgram)
-                        .setSeasonNumber(SEASON_NUMBER2)
-                        .setEpisodeNumber(EPISODE_NUMBER2)
-                        .build();
-        programs.add(program3);
-        Program program4 = new ProgramImpl.Builder(program1).setStartTimeUtcMillis(1).build();
-        programs.add(program4);
-        LongSparseArray<List<Program>> result =
-                SeriesRecordingScheduler.pickOneProgramPerEpisode(
-                        mDataManager, Collections.singletonList(seriesRecording), programs);
-        assertThat(result.get(SERIES_RECORDING_ID1)).containsExactly(program1, program3);
-    }
-
-    @Test
-    public void testPickOneProgramPerEpisode_nullEpisode() {
-        SeriesRecording seriesRecording =
-                SeriesRecording.buildFrom(mBaseSeriesRecording).setId(SERIES_RECORDING_ID1).build();
-        mDataManager.addSeriesRecording(seriesRecording);
-        List<Program> programs = new ArrayList<>();
-        Program program1 = new ProgramImpl.Builder(mBaseProgram).setStartTimeUtcMillis(0).build();
-        programs.add(program1);
-        Program program2 = new ProgramImpl.Builder(mBaseProgram).setStartTimeUtcMillis(1).build();
-        programs.add(program2);
-        LongSparseArray<List<Program>> result =
-                SeriesRecordingScheduler.pickOneProgramPerEpisode(
-                        mDataManager, Collections.singletonList(seriesRecording), programs);
-        assertThat(result.get(SERIES_RECORDING_ID1)).containsExactly(program1, program2);
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/dvr/ui/SortedArrayAdapterTest.java b/tests/robotests/src/com/android/tv/dvr/ui/SortedArrayAdapterTest.java
deleted file mode 100644
index aa90d41..0000000
--- a/tests/robotests/src/com/android/tv/dvr/ui/SortedArrayAdapterTest.java
+++ /dev/null
@@ -1,255 +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 static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
-
-import androidx.leanback.widget.ClassPresenterSelector;
-import androidx.leanback.widget.ObjectAdapter;
-
-import com.android.tv.testing.constants.ConfigConstants;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.Objects;
-
-/** Tests for {@link SortedArrayAdapter}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-public class SortedArrayAdapterTest {
-    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;
-
-    @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);
-        assertNotEmpty();
-        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));
-        assertNotEmpty();
-        assertThat(mAdapter.size()).isEqualTo(1);
-        assertThat(mAdapter.get(0)).isEqualTo(P2);
-    }
-
-    @Test
-    public void testExtraItem() {
-        mAdapter = new TestSortedArrayAdapter(Integer.MAX_VALUE, EXTRA);
-        mAdapter.setInitialItems(Arrays.asList(P1, P2));
-        assertNotEmpty();
-        assertThat(mAdapter.size()).isEqualTo(3);
-        assertThat(mAdapter.get(0)).isEqualTo(P2);
-        assertThat(mAdapter.get(2)).isEqualTo(EXTRA);
-        mAdapter.remove(P2);
-        mAdapter.remove(P1);
-        assertThat(mAdapter.size()).isEqualTo(1);
-        assertThat(mAdapter.get(0)).isEqualTo(EXTRA);
-    }
-
-    @Test
-    public void testExtraItemWithMaxCount() {
-        mAdapter = new TestSortedArrayAdapter(1, EXTRA);
-        mAdapter.setInitialItems(Arrays.asList(P1, P2));
-        assertNotEmpty();
-        assertThat(mAdapter.size()).isEqualTo(2);
-        assertThat(mAdapter.get(0)).isEqualTo(P2);
-        assertThat(mAdapter.get(1)).isEqualTo(EXTRA);
-        mAdapter.remove(P2);
-        assertThat(mAdapter.size()).isEqualTo(1);
-        assertThat(mAdapter.get(0)).isEqualTo(EXTRA);
-    }
-
-    @Test
-    public void testRemove() {
-        mAdapter.add(P1);
-        mAdapter.add(P2);
-        assertNotEmpty();
-        assertContentsInOrder(mAdapter, P2, P1);
-        mAdapter.remove(P3);
-        assertContentsInOrder(mAdapter, P2, P1);
-        mAdapter.remove(P2);
-        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);
-        mAdapter.add(P2);
-        assertNotEmpty();
-        assertContentsInOrder(mAdapter, P2, P1);
-        mAdapter.change(p2_changed);
-        assertContentsInOrder(mAdapter, P1, p2_changed);
-    }
-
-    @Test
-    public void testChange_new() {
-        mAdapter.change(P1);
-        assertNotEmpty();
-        assertContentsInOrder(mAdapter, P1);
-    }
-
-    private void assertEmpty() {
-        assertWithMessage("empty").that(mAdapter.isEmpty()).isTrue();
-    }
-
-    private void assertNotEmpty() {
-        assertWithMessage("empty").that(mAdapter.isEmpty()).isFalse();
-    }
-
-    private static void assertContentsInOrder(ObjectAdapter adapter, Object... contents) {
-        int ex = contents.length;
-        assertWithMessage("size").that(adapter.size()).isEqualTo(ex);
-        for (int i = 0; i < ex; i++) {
-            assertWithMessage("element " + 1).that(adapter.get(i)).isEqualTo(contents[i]);
-        }
-    }
-
-    private static class TestData {
-        @Override
-        public String toString() {
-            return "TestData[" + mId + "]{" + mText + '}';
-        }
-
-        static TestData create(long first, String text) {
-            return new TestData(first, text);
-        }
-
-        private final long mId;
-        private final String mText;
-
-        private TestData(long id, String second) {
-            this.mId = id;
-            this.mText = second;
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (!(o instanceof TestData)) return false;
-            TestData that = (TestData) o;
-            return mId == that.mId && Objects.equals(mText, that.mText);
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(mId, mText);
-        }
-    }
-
-    private static class TestSortedArrayAdapter extends SortedArrayAdapter<TestData> {
-
-        private static final Comparator<TestData> TEXT_COMPARATOR =
-                new Comparator<TestData>() {
-                    @Override
-                    public int compare(TestData lhs, TestData rhs) {
-                        return lhs.mText.compareTo(rhs.mText);
-                    }
-                };
-
-        TestSortedArrayAdapter(int maxInitialCount, Object extra) {
-            super(new ClassPresenterSelector(), TEXT_COMPARATOR, maxInitialCount);
-            if (extra != null) {
-                addExtraItem((TestData) extra);
-            }
-        }
-
-        @Override
-        protected long getId(TestData item) {
-            return item.mId;
-        }
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/dvr/ui/browse/DvrBrowseFragmentTest.java b/tests/robotests/src/com/android/tv/dvr/ui/browse/DvrBrowseFragmentTest.java
deleted file mode 100644
index 25a4256..0000000
--- a/tests/robotests/src/com/android/tv/dvr/ui/browse/DvrBrowseFragmentTest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2018 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 com.android.tv.dvr.data.RecordedProgram;
-import com.android.tv.dvr.data.ScheduledRecording;
-import com.android.tv.testing.ComparatorTester;
-import com.android.tv.testing.constants.ConfigConstants;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-/** Test for {@link DvrBrowseFragment}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-public class DvrBrowseFragmentTest {
-
-    @Test
-    public void testRecentRowComparator_scheduledRecordings_latestFirst() {
-        ComparatorTester comparatorTester =
-                new ComparatorTester(DvrBrowseFragment.RECENT_ROW_COMPARATOR)
-                        .permitInconsistencyWithEquals();
-        // priority (highest to lowest): start time, class, ID
-        comparatorTester.addEqualityGroup(buildRecordedProgramForTest(2, 120, 150));
-        comparatorTester.addEqualityGroup(buildRecordedProgramForTest(1, 120, 150));
-        comparatorTester.addEqualityGroup(buildScheduledRecordingForTest(1, 120, 150));
-        comparatorTester.addEqualityGroup(buildScheduledRecordingForTest(2, 120, 150));
-        comparatorTester.addEqualityGroup(buildRecordedProgramForTest(4, 100, 200));
-        comparatorTester.addEqualityGroup(buildRecordedProgramForTest(3, 100, 200));
-        comparatorTester.addEqualityGroup(buildScheduledRecordingForTest(3, 100, 200));
-        comparatorTester.addEqualityGroup(buildScheduledRecordingForTest(4, 100, 200));
-        comparatorTester.addEqualityGroup(new Object(), Long.valueOf("777"), "string");
-        comparatorTester.testCompare();
-    }
-
-    private ScheduledRecording buildScheduledRecordingForTest(long id, long start, long end) {
-        return ScheduledRecording.builder("test", 1, start, end).setId(id).build();
-    }
-
-    private RecordedProgram buildRecordedProgramForTest(long id, long start, long end) {
-        return RecordedProgram.builder()
-                .setId(id)
-                .setInputId("test")
-                .setStartTimeUtcMillis(start)
-                .setEndTimeUtcMillis(end)
-                .build();
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/dvr/ui/list/DvrHistoryRowAdapterTest.java b/tests/robotests/src/com/android/tv/dvr/ui/list/DvrHistoryRowAdapterTest.java
deleted file mode 100644
index 5d247e3..0000000
--- a/tests/robotests/src/com/android/tv/dvr/ui/list/DvrHistoryRowAdapterTest.java
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * Copyright (C) 2018 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 static com.google.common.truth.Truth.assertThat;
-
-import androidx.leanback.widget.ClassPresenterSelector;
-
-import com.android.tv.common.flags.impl.DefaultUiFlags;
-import com.android.tv.common.util.Clock;
-import com.android.tv.dvr.data.RecordedProgram;
-import com.android.tv.dvr.data.ScheduledRecording;
-import com.android.tv.testing.TvRobolectricTestRunner;
-import com.android.tv.testing.TestSingletonApp;
-import com.android.tv.testing.constants.ConfigConstants;
-import com.android.tv.testing.dvr.DvrDataManagerInMemoryImpl;
-import com.android.tv.testing.fakes.FakeClock;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/** Test for {@link DvrHistoryRowAdapter}. */
-@RunWith(TvRobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK, application = TestSingletonApp.class)
-public class DvrHistoryRowAdapterTest {
-
-    private static final ScheduledRecording SCHEDULE_1 =
-            buildScheduledRecordingForTest(
-                    2,
-                    1518249600000L, // 2/10/2018 0:00 PST
-                    1518250600000L,
-                    ScheduledRecording.STATE_RECORDING_FAILED);
-    private static final ScheduledRecording SCHEDULE_1_COPY =
-            buildScheduledRecordingForTest(
-                    3,
-                    1518249600000L, // 2/10/2018 0:00 PST
-                    1518250600000L,
-                    ScheduledRecording.STATE_RECORDING_FAILED);
-    private static final ScheduledRecording SCHEDULE_2 =
-            buildScheduledRecordingForTest(
-                    4,
-                    1518595200000L, // 2/14/2018 0:00 PST
-                    1518596200000L,
-                    ScheduledRecording.STATE_RECORDING_FAILED);
-    private static final ScheduledRecording SCHEDULE_2_COPY =
-            buildScheduledRecordingForTest(
-                    5,
-                    1518595200000L, // 2/14/2018 0:00 PST
-                    1518596200000L,
-                    ScheduledRecording.STATE_RECORDING_FAILED);
-
-    private static RecordedProgram sRecordedProgram;
-    private static final long FAKE_CURRENT_TIME = 1518764400000L; // 2/15/2018 23:00 PST
-
-    private DvrHistoryRowAdapter mDvrHistoryRowAdapter;
-    private DvrDataManagerInMemoryImpl mDvrDataManager;
-
-    @Before
-    public void setUp() {
-        sRecordedProgram =
-                buildRecordedProgramForTest(
-                        6,
-                        1518249600000L, // 2/10/2018 0:00 PST
-                        1518250600000L);
-
-        TestSingletonApp app = (TestSingletonApp) RuntimeEnvironment.application;
-        Clock clock = FakeClock.createWithTime(FAKE_CURRENT_TIME);
-
-        mDvrDataManager = new DvrDataManagerInMemoryImpl(app, clock);
-        app.mDvrDataManager = mDvrDataManager;
-        // keep the original IDs instead of creating a new one.
-        mDvrDataManager.addScheduledRecording(
-                true, SCHEDULE_1, SCHEDULE_1_COPY, SCHEDULE_2, SCHEDULE_2_COPY);
-
-        ClassPresenterSelector presenterSelector = new ClassPresenterSelector();
-        mDvrHistoryRowAdapter =
-                new DvrHistoryRowAdapter(
-                        RuntimeEnvironment.application,
-                        presenterSelector,
-                        clock,
-                        mDvrDataManager,
-                        new DefaultUiFlags());
-    }
-
-    @Test
-    public void testStart() {
-        mDvrHistoryRowAdapter.start();
-        assertInitialState();
-    }
-
-    @Test
-    public void testOnScheduledRecordingAdded_existingHeader() {
-        mDvrHistoryRowAdapter.start();
-        ScheduledRecording toAdd =
-                buildScheduledRecordingForTest(
-                        6,
-                        1518249600000L, // 2/10/2018
-                        1518250600000L,
-                        ScheduledRecording.STATE_RECORDING_FAILED);
-        mDvrHistoryRowAdapter.onScheduledRecordingAdded(toAdd);
-
-        // a schedule row is added
-        assertThat(mDvrHistoryRowAdapter.size()).isEqualTo(7);
-        assertThat(getHeaderItemCounts()).containsExactly(2, 3).inOrder();
-        assertThat(getScheduleSize()).isEqualTo(5);
-    }
-
-    @Test
-    public void testOnScheduledRecordingAdded_newHeader_addOldest() {
-        mDvrHistoryRowAdapter.start();
-        ScheduledRecording toAdd =
-                buildScheduledRecordingForTest(
-                        6,
-                        1518159600000L, // 2/8/2018 PST
-                        1518160600000L,
-                        ScheduledRecording.STATE_RECORDING_FAILED);
-        mDvrHistoryRowAdapter.onScheduledRecordingAdded(toAdd);
-
-        // a header row and a schedule row are added
-        assertThat(mDvrHistoryRowAdapter.size()).isEqualTo(8);
-        assertThat(getHeaderItemCounts()).containsExactly(2, 2, 1).inOrder();
-        assertThat(getScheduleSize()).isEqualTo(5);
-    }
-
-    @Test
-    public void testOnScheduledRecordingAdded_newHeader_addBetween() {
-        mDvrHistoryRowAdapter.start();
-        ScheduledRecording toAdd =
-                buildScheduledRecordingForTest(
-                        6,
-                        1518336000000L, // 2/11/2018 PST
-                        1518337000000L,
-                        ScheduledRecording.STATE_RECORDING_FAILED);
-        mDvrHistoryRowAdapter.onScheduledRecordingAdded(toAdd);
-
-        // a header row and a schedule row are added
-        assertThat(mDvrHistoryRowAdapter.size()).isEqualTo(8);
-        assertThat(getHeaderItemCounts()).containsExactly(2, 1, 2).inOrder();
-        assertThat(getScheduleSize()).isEqualTo(5);
-    }
-
-    @Test
-    public void testOnScheduledRecordingAdded_newHeader_addNewest() {
-        mDvrHistoryRowAdapter.start();
-        ScheduledRecording toAdd =
-                buildScheduledRecordingForTest(
-                        6,
-                        1518681600000L, // 2/15/2018 PST
-                        1518682600000L,
-                        ScheduledRecording.STATE_RECORDING_FAILED);
-        mDvrHistoryRowAdapter.onScheduledRecordingAdded(toAdd);
-
-        // a header row and a schedule row are added
-        assertThat(mDvrHistoryRowAdapter.size()).isEqualTo(8);
-        assertThat(getHeaderItemCounts()).containsExactly(1, 2, 2).inOrder();
-        assertThat(getScheduleSize()).isEqualTo(5);
-    }
-
-    @Test
-    public void testOnScheduledRecordingAdded_addRecordedProgram() {
-        mDvrHistoryRowAdapter.start();
-        mDvrHistoryRowAdapter.onScheduledRecordingAdded(sRecordedProgram);
-
-        // a header row and a schedule row are added
-        assertThat(mDvrHistoryRowAdapter.size()).isEqualTo(7);
-        assertThat(getHeaderItemCounts()).containsExactly(2, 3).inOrder();
-        assertThat(getScheduleSize()).isEqualTo(5);
-    }
-
-    @Test
-    public void testOnScheduledRecordingRemoved_keepHeader() {
-        mDvrHistoryRowAdapter.start();
-        mDvrHistoryRowAdapter.onScheduledRecordingRemoved(SCHEDULE_1);
-
-        // a schedule row is removed
-        assertThat(mDvrHistoryRowAdapter.size()).isEqualTo(5);
-        assertThat(getHeaderItemCounts()).containsExactly(2, 1).inOrder();
-        assertThat(getScheduleSize()).isEqualTo(3);
-    }
-
-    @Test
-    public void testOnScheduledRecordingRemoved_removeHeader() {
-        mDvrHistoryRowAdapter.start();
-        mDvrHistoryRowAdapter.onScheduledRecordingRemoved(SCHEDULE_1);
-        mDvrHistoryRowAdapter.onScheduledRecordingRemoved(SCHEDULE_1_COPY);
-
-        // a header row and a schedule row are removed
-        assertThat(mDvrHistoryRowAdapter.size()).isEqualTo(3);
-        assertThat(getHeaderItemCounts()).containsExactly(2).inOrder();
-        assertThat(getScheduleSize()).isEqualTo(2);
-    }
-
-    @Test
-    public void testOnScheduledRecordingRemoved_removeRecordedProgram() {
-        mDvrDataManager.addRecordedProgramInternal(sRecordedProgram, true);
-        mDvrHistoryRowAdapter.start();
-        assertThat(mDvrHistoryRowAdapter.size()).isEqualTo(7);
-        assertThat(getHeaderItemCounts()).containsExactly(2, 3).inOrder();
-        assertThat(getScheduleSize()).isEqualTo(5);
-
-        mDvrHistoryRowAdapter.onScheduledRecordingRemoved(sRecordedProgram);
-
-        // a schedule row is removed
-        assertThat(mDvrHistoryRowAdapter.size()).isEqualTo(6);
-        assertThat(getHeaderItemCounts()).containsExactly(2, 2);
-        assertThat(getScheduleSize()).isEqualTo(4);
-    }
-
-    private static ScheduledRecording buildScheduledRecordingForTest(
-            long id, long startTime, long endTime, int state) {
-        ScheduledRecording.Builder builder =
-                ScheduledRecording.builder("fakeInput", 1, startTime, endTime)
-                        .setId(id)
-                        .setState(state);
-        return builder.build();
-    }
-
-    private static RecordedProgram buildRecordedProgramForTest(
-            long id, long startTime, long endTime) {
-        RecordedProgram.Builder builder =
-                RecordedProgram.builder()
-                        .setId(id)
-                        .setInputId("fakeInput")
-                        .setStartTimeUtcMillis(startTime)
-                        .setEndTimeUtcMillis(endTime);
-        return builder.build();
-    }
-
-    private int getScheduleSize() {
-        int size = 0;
-        for (int i = 0; i < mDvrHistoryRowAdapter.size(); i++) {
-            Object item = mDvrHistoryRowAdapter.get(i);
-            if (item instanceof ScheduleRow && ((ScheduleRow) item).getSchedule() != null) {
-                size++;
-            }
-        }
-        return size;
-    }
-
-    private List<Integer> getHeaderItemCounts() {
-        List<Integer> result = new ArrayList<>();
-        for (int i = 0; i < mDvrHistoryRowAdapter.size(); i++) {
-            Object item = mDvrHistoryRowAdapter.get(i);
-            if (item instanceof SchedulesHeaderRow) {
-                int count = ((SchedulesHeaderRow) item).getItemCount();
-                assertThat(count).isAtLeast(1);
-                result.add(count);
-            }
-        }
-        return result;
-    }
-
-    private void assertInitialState() {
-        assertThat(mDvrHistoryRowAdapter.size()).isEqualTo(6);
-        assertThat(getHeaderItemCounts()).containsExactly(2, 2).inOrder();
-        assertThat(getScheduleSize()).isEqualTo(4);
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/dvr/ui/playback/DvrPlayerTest.java b/tests/robotests/src/com/android/tv/dvr/ui/playback/DvrPlayerTest.java
deleted file mode 100644
index ad0ddf3..0000000
--- a/tests/robotests/src/com/android/tv/dvr/ui/playback/DvrPlayerTest.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2018 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 static com.google.common.truth.Truth.assertThat;
-
-import android.media.tv.TvTrackInfo;
-
-import com.android.tv.ShadowTvView;
-import com.android.tv.testing.TestSingletonApp;
-import com.android.tv.testing.constants.ConfigConstants;
-import com.android.tv.ui.AppLayerTvView;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadow.api.Shadow;
-
-import java.util.ArrayList;
-import java.util.Collections;
-
-/** Test for {@link DvrPlayer}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(
-        sdk = ConfigConstants.SDK,
-        application = TestSingletonApp.class,
-        shadows = {ShadowTvView.class})
-public class DvrPlayerTest {
-    private ShadowTvView mShadowTvView;
-    private DvrPlayer mDvrPlayer;
-
-    @Before
-    public void setUp() {
-        AppLayerTvView tvView = new AppLayerTvView(RuntimeEnvironment.application);
-        mShadowTvView = Shadow.extract(tvView);
-        mDvrPlayer = new DvrPlayer(tvView, RuntimeEnvironment.application);
-    }
-
-    @Test
-    public void testGetAudioTracks_null() {
-        mShadowTvView.mTracks.put(TvTrackInfo.TYPE_AUDIO, null);
-        assertThat(mDvrPlayer.getAudioTracks()).isNotNull();
-        assertThat(mDvrPlayer.getAudioTracks()).isEmpty();
-    }
-
-    @Test
-    public void testGetAudioTracks_empty() {
-        mShadowTvView.mTracks.put(TvTrackInfo.TYPE_AUDIO, new ArrayList<>());
-        assertThat(mDvrPlayer.getAudioTracks()).isNotNull();
-        assertThat(mDvrPlayer.getAudioTracks()).isEmpty();
-    }
-
-    @Test
-    public void testGetAudioTracks_nonEmpty() {
-        TvTrackInfo info = new TvTrackInfo.Builder(TvTrackInfo.TYPE_AUDIO, "fake id").build();
-        mShadowTvView.mTracks.put(TvTrackInfo.TYPE_AUDIO, Collections.singletonList(info));
-        assertThat(mDvrPlayer.getAudioTracks()).containsExactly(info);
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/guide/ProgramItemViewTest.java b/tests/robotests/src/com/android/tv/guide/ProgramItemViewTest.java
deleted file mode 100644
index e7850c1..0000000
--- a/tests/robotests/src/com/android/tv/guide/ProgramItemViewTest.java
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * Copyright (C) 2019 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.guide;
-
-import static com.google.android.libraries.testing.truth.TextViewSubject.assertThat;
-
-import android.support.annotation.NonNull;
-import android.view.LayoutInflater;
-
-import com.android.tv.R;
-import com.android.tv.common.util.Clock;
-import com.android.tv.data.ChannelDataManager;
-import com.android.tv.data.ProgramImpl;
-import com.android.tv.dvr.DvrManager;
-import com.android.tv.dvr.data.ScheduledRecording;
-import com.android.tv.guide.ProgramItemViewTest.TestApp;
-import com.android.tv.guide.ProgramItemViewTest.TestModule.Contributes;
-import com.android.tv.guide.ProgramManager.TableEntry;
-import com.android.tv.testing.TestSingletonApp;
-import com.android.tv.testing.constants.ConfigConstants;
-import com.android.tv.testing.robo.RobotTestAppHelper;
-import com.android.tv.testing.testdata.TestData;
-
-import dagger.Component;
-import dagger.Module;
-import dagger.Provides;
-import dagger.android.AndroidInjectionModule;
-import dagger.android.AndroidInjector;
-import dagger.android.ContributesAndroidInjector;
-import dagger.android.DispatchingAndroidInjector;
-import dagger.android.HasAndroidInjector;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-import java.time.Duration;
-import java.util.concurrent.TimeUnit;
-
-import javax.inject.Inject;
-
-/** Tests for {@link ProgramItemView}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK, application = TestApp.class)
-public class ProgramItemViewTest {
-
-    /** TestApp for {@link ProgramItemViewTest} */
-    public static class TestApp extends TestSingletonApp implements HasAndroidInjector {
-        @Inject DispatchingAndroidInjector<Object> dispatchingAndroidInjector;
-
-        @Override
-        public void onCreate() {
-            super.onCreate();
-            DaggerProgramItemViewTest_TestAppComponent.builder()
-                    .testModule(new TestModule(this))
-                    .build()
-                    .inject(this);
-        }
-
-        @Override
-        public AndroidInjector<Object> androidInjector() {
-            return dispatchingAndroidInjector;
-        }
-    }
-
-    /** Component for {@link ProgramItemViewTest} */
-    @Component(
-            modules = {
-                AndroidInjectionModule.class,
-                TestModule.class,
-            })
-    interface TestAppComponent extends AndroidInjector<TestApp> {}
-
-    /** Module for {@link ProgramItemViewTest} */
-    @Module(includes = {Contributes.class})
-    public static class TestModule {
-
-        @Module()
-        public abstract static class Contributes {
-            @ContributesAndroidInjector
-            abstract ProgramItemView contributesProgramItemView();
-        }
-
-        private final TestApp myTestApp;
-
-        TestModule(TestApp test) {
-            myTestApp = test;
-        }
-
-        @Provides
-        ChannelDataManager providesChannelDataManager() {
-            return myTestApp.getChannelDataManager();
-        }
-
-        @Provides
-        Clock provideClock() {
-            return myTestApp.getClock();
-        }
-    }
-
-    //  Thursday, June 1, 2017 1:00:00 PM GMT-07:00
-    private final long testStartTimeMs = 1496347200000L;
-
-    // Thursday, June 1, 2017 8:00:00 PM GMT-07:00
-    private final long eightPM = 1496372400000L;
-    private final ProgramImpl baseProgram =
-            new ProgramImpl.Builder()
-                    .setChannelId(1)
-                    .setStartTimeUtcMillis(eightPM)
-                    .setEndTimeUtcMillis(eightPM + Duration.ofHours(1).toMillis())
-                    .build();
-
-    private ProgramItemView mPprogramItemView;
-
-    @Mock DvrManager dvrManager;
-
-    @Before
-    public void setup() {
-        MockitoAnnotations.initMocks(this);
-        TestSingletonApp app = (TestSingletonApp) RuntimeEnvironment.application;
-        app.dvrManager = dvrManager;
-        app.fakeClock.setBootTimeMillis(testStartTimeMs + TimeUnit.HOURS.toMillis(-12));
-        app.fakeClock.setCurrentTimeMillis(testStartTimeMs);
-        RobotTestAppHelper.loadTestData(app, TestData.DEFAULT_10_CHANNELS);
-        mPprogramItemView =
-                (ProgramItemView)
-                        LayoutInflater.from(RuntimeEnvironment.application)
-                                .inflate(R.layout.program_guide_table_item, null);
-        GuideUtils.setWidthPerHour(100);
-    }
-
-    @Test
-    public void initialState() {
-        assertThat(mPprogramItemView).hasEmptyText();
-    }
-
-    @Test
-    public void setValue_noProgram() {
-        TableEntry tableEntry = create30MinuteTableEntryFor(null, null, false);
-        mPprogramItemView.setValues(null, tableEntry, 0, 0, 0, "a gap");
-        assertThat(mPprogramItemView).hasText("a gap");
-        assertThat(mPprogramItemView).hasContentDescription("1 a gap 8:00 – 9:00 PM");
-    }
-
-    @Test
-    public void setValue_programNoTitle() {
-        ProgramImpl program = new ProgramImpl.Builder(baseProgram).build();
-        TableEntry tableEntry = create30MinuteTableEntryFor(program, null, false);
-        mPprogramItemView.setValues(null, tableEntry, 0, 0, 0, "a gap");
-        assertThat(mPprogramItemView).hasText("No information");
-        assertThat(mPprogramItemView).hasContentDescription("1 No information 8:00 – 9:00 PM");
-    }
-
-    @Test
-    public void setValue_programTitle() {
-        ProgramImpl program =
-                new ProgramImpl.Builder(baseProgram).setTitle("A good program").build();
-        TableEntry tableEntry = create30MinuteTableEntryFor(program, null, false);
-        mPprogramItemView.setValues(null, tableEntry, 0, 0, 0, "a gap");
-        assertThat(mPprogramItemView).hasText("A good program");
-        assertThat(mPprogramItemView).hasContentDescription("1 A good program 8:00 – 9:00 PM");
-    }
-
-    @Test
-    public void setValue_programDescriptionBlocked() {
-        ProgramImpl program =
-                new ProgramImpl.Builder(baseProgram)
-                        .setTitle("A good program")
-                        .setDescription("Naughty")
-                        .build();
-        TableEntry tableEntry = create30MinuteTableEntryFor(program, null, true);
-        mPprogramItemView.setValues(null, tableEntry, 0, 0, 0, "a gap");
-        assertThat(mPprogramItemView).hasText("A good program");
-        assertThat(mPprogramItemView)
-                .hasContentDescription("1 A good program 8:00 – 9:00 PM This program is blocked");
-    }
-
-    @Test
-    public void setValue_programEpisode() {
-        ProgramImpl program =
-                new ProgramImpl.Builder(baseProgram)
-                        .setTitle("A good program")
-                        .setEpisodeTitle("The one with an episode")
-                        .build();
-        TableEntry tableEntry = create30MinuteTableEntryFor(program, null, false);
-        mPprogramItemView.setValues(null, tableEntry, 0, 0, 0, "a gap");
-        assertThat(mPprogramItemView).hasText("A good program\n\u200DThe one with an episode");
-        assertThat(mPprogramItemView)
-                .hasContentDescription("1 A good program 8:00 – 9:00 PM The one with an episode");
-    }
-
-    @Test
-    public void setValue_programEpisodeAndDescrition() {
-        ProgramImpl program =
-                new ProgramImpl.Builder(baseProgram)
-                        .setTitle("A good program")
-                        .setEpisodeTitle("The one with an episode")
-                        .setDescription("Jack and Jill go up a hill")
-                        .build();
-        TableEntry tableEntry = create30MinuteTableEntryFor(program, null, false);
-        mPprogramItemView.setValues(null, tableEntry, 0, 0, 0, "a gap");
-        assertThat(mPprogramItemView).hasText("A good program\n\u200DThe one with an episode");
-        assertThat(mPprogramItemView)
-                .hasContentDescription(
-                        "1 A good program 8:00 – 9:00 PM The one with an episode"
-                                + " Jack and Jill go up a hill");
-    }
-
-    @Test
-    public void setValue_scheduledConflict() {
-        ProgramImpl program =
-                new ProgramImpl.Builder(baseProgram).setTitle("A good program").build();
-        ScheduledRecording scheduledRecording =
-                ScheduledRecording.builder("input1", program).build();
-        TableEntry tableEntry = create30MinuteTableEntryFor(program, scheduledRecording, false);
-        Mockito.when(dvrManager.isConflicting(scheduledRecording)).thenReturn(true);
-
-        mPprogramItemView.setValues(null, tableEntry, 0, 0, 0, "a gap");
-        assertThat(mPprogramItemView).hasText("A good program");
-        assertThat(mPprogramItemView)
-                .hasContentDescription("1 A good program 8:00 – 9:00 PM Recording conflict");
-    }
-
-    @Test
-    public void setValue_scheduled() {
-        ProgramImpl program =
-                new ProgramImpl.Builder(baseProgram).setTitle("A good program").build();
-        ScheduledRecording scheduledRecording =
-                ScheduledRecording.builder("input1", program)
-                        .setState(ScheduledRecording.STATE_RECORDING_NOT_STARTED)
-                        .build();
-        TableEntry tableEntry = create30MinuteTableEntryFor(program, scheduledRecording, false);
-        Mockito.when(dvrManager.isConflicting(scheduledRecording)).thenReturn(false);
-
-        mPprogramItemView.setValues(null, tableEntry, 0, 0, 0, "a gap");
-        assertThat(mPprogramItemView).hasText("A good program");
-        assertThat(mPprogramItemView)
-                .hasContentDescription("1 A good program 8:00 – 9:00 PM Recording scheduled");
-    }
-
-    @Test
-    public void setValue_recordingInProgress() {
-        ProgramImpl program =
-                new ProgramImpl.Builder(baseProgram).setTitle("A good program").build();
-        ScheduledRecording scheduledRecording =
-                ScheduledRecording.builder("input1", program)
-                        .setState(ScheduledRecording.STATE_RECORDING_IN_PROGRESS)
-                        .build();
-        TableEntry tableEntry = create30MinuteTableEntryFor(program, scheduledRecording, false);
-        Mockito.when(dvrManager.isConflicting(scheduledRecording)).thenReturn(false);
-
-        mPprogramItemView.setValues(null, tableEntry, 0, 0, 0, "a gap");
-        assertThat(mPprogramItemView).hasText("A good program");
-        assertThat(mPprogramItemView)
-                .hasContentDescription("1 A good program 8:00 – 9:00 PM Recording");
-    }
-
-    @NonNull
-    private TableEntry create30MinuteTableEntryFor(
-            ProgramImpl program, ScheduledRecording scheduledRecording, boolean isBlocked) {
-        return ProgramManager.createTableEntryForTest(
-                1,
-                program,
-                scheduledRecording,
-                eightPM,
-                eightPM + Duration.ofHours(1).toMillis(),
-                isBlocked);
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/guide/ProgramTableAdapterTest.java b/tests/robotests/src/com/android/tv/guide/ProgramTableAdapterTest.java
deleted file mode 100644
index 5207274..0000000
--- a/tests/robotests/src/com/android/tv/guide/ProgramTableAdapterTest.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2019 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.guide;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.anyLong;
-
-import com.android.tv.common.flags.impl.DefaultUiFlags;
-import com.android.tv.data.ChannelDataManager;
-import com.android.tv.data.ChannelImpl;
-import com.android.tv.data.GenreItems;
-import com.android.tv.data.ProgramDataManager;
-import com.android.tv.data.ProgramImpl;
-import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
-import com.android.tv.testing.TestSingletonApp;
-import com.android.tv.testing.constants.ConfigConstants;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-/** Tests for {@link ProgramTableAdapter}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK, application = TestSingletonApp.class)
-public class ProgramTableAdapterTest {
-
-    @Mock private ProgramGuide mProgramGuide;
-    @Mock private ChannelDataManager mChannelDataManager;
-    @Mock private ProgramDataManager mProgramDataManager;
-    private ProgramManager mProgramManager;
-
-    //  Thursday, June 1, 2017 1:00:00 PM GMT-07:00
-    private final long mTestStartTimeMs = 1496347200000L;
-    // Thursday, June 1, 2017 8:00:00 PM GMT-07:00
-    private final long mEightPM = 1496372400000L;
-    private DefaultUiFlags mUiFlags;
-
-    @Before
-    public void setup() {
-        MockitoAnnotations.initMocks(this);
-        TestSingletonApp app = (TestSingletonApp) RuntimeEnvironment.application;
-        app.fakeClock.setBootTimeMillis(mTestStartTimeMs + TimeUnit.HOURS.toMillis(-12));
-        app.fakeClock.setCurrentTimeMillis(mTestStartTimeMs);
-        mUiFlags = new DefaultUiFlags();
-        mProgramManager =
-                new ProgramManager(
-                        app.getTvInputManagerHelper(),
-                        mChannelDataManager,
-                        mProgramDataManager,
-                        null,
-                        null);
-    }
-
-    @Test
-    public void testOnTableEntryChanged() {
-        Mockito.when(mProgramGuide.getProgramManager()).thenReturn(mProgramManager);
-        Mockito.when(mProgramDataManager.getCurrentProgram(anyLong()))
-                .thenAnswer(
-                        invocation -> {
-                            long id = (long) invocation.getArguments()[0];
-                            return buildProgramForTesting(
-                                    id, id, (int) id % GenreItems.getGenreCount());
-                        });
-        ProgramTableAdapter programTableAdapter =
-                new ProgramTableAdapter(RuntimeEnvironment.application, mProgramGuide, mUiFlags);
-        mProgramManager.setChannels(buildChannelForTesting(1, 2, 3));
-        assertThat(mProgramManager.getChannelCount()).isEqualTo(3);
-
-        // set genre ID to 1. Then channel 1 is in the filtered list but channel 2 is not.
-        mProgramManager.resetChannelListWithGenre(1);
-        assertThat(mProgramManager.getChannelCount()).isEqualTo(1);
-        assertThat(mProgramManager.getChannelIndex(2)).isEqualTo(-1);
-
-        // should be no exception when onTableEntryChanged() is called
-        programTableAdapter.onTableEntryChanged(
-                ProgramManager.createTableEntryForTest(
-                        2,
-                        mProgramDataManager.getCurrentProgram(2),
-                        null,
-                        mTestStartTimeMs,
-                        mEightPM,
-                        false));
-    }
-
-    private List<Channel> buildChannelForTesting(long... ids) {
-        List<Channel> channels = new ArrayList<>();
-        for (long id : ids) {
-            channels.add(new ChannelImpl.Builder().setId(id).build());
-        }
-        return channels;
-    }
-
-    private Program buildProgramForTesting(long id, long channelId, int genreId) {
-        return new ProgramImpl.Builder()
-                .setId(id)
-                .setChannelId(channelId)
-                .setCanonicalGenres(GenreItems.getCanonicalGenre(genreId))
-                .build();
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/search/FakeSearchInterface.java b/tests/robotests/src/com/android/tv/search/FakeSearchInterface.java
deleted file mode 100644
index 568bddd..0000000
--- a/tests/robotests/src/com/android/tv/search/FakeSearchInterface.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2018 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 android.content.Intent;
-import android.media.tv.TvContract;
-import android.media.tv.TvContract.Programs;
-
-import com.android.tv.data.api.Program;
-import com.android.tv.search.LocalSearchProvider.SearchResult;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/** Fake {@link SearchInterface} for testing. */
-public class FakeSearchInterface implements SearchInterface {
-    public final List<Program> mPrograms = new ArrayList<>();
-
-    @Override
-    public List<SearchResult> search(String query, int limit, int action) {
-
-        List<SearchResult> results = new ArrayList<>();
-        for (Program program : mPrograms) {
-            if (program.getTitle().contains(query) || program.getDescription().contains(query)) {
-                results.add(fromProgram(program));
-            }
-        }
-        return results;
-    }
-
-    public static SearchResult fromProgram(Program program) {
-        SearchResult.Builder result = SearchResult.builder();
-        result.setTitle(program.getTitle());
-        result.setDescription(
-                program.getStartTimeUtcMillis() + " - " + program.getEndTimeUtcMillis());
-        result.setImageUri(program.getPosterArtUri());
-        result.setIntentAction(Intent.ACTION_VIEW);
-        result.setIntentData(TvContract.buildChannelUri(program.getChannelId()).toString());
-        result.setIntentExtraData(TvContract.buildProgramUri(program.getId()).toString());
-        result.setContentType(Programs.CONTENT_ITEM_TYPE);
-        result.setIsLive(true);
-        result.setVideoWidth(program.getVideoWidth());
-        result.setVideoHeight(program.getVideoHeight());
-        result.setDuration(program.getDurationMillis());
-        result.setChannelId(program.getChannelId());
-        return result.build();
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/search/LocalSearchProviderTest.java b/tests/robotests/src/com/android/tv/search/LocalSearchProviderTest.java
deleted file mode 100644
index 7615126..0000000
--- a/tests/robotests/src/com/android/tv/search/LocalSearchProviderTest.java
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * 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 com.google.common.truth.Truth.assertThat;
-
-import static junit.framework.Assert.fail;
-
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.verify;
-
-import android.app.SearchManager;
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.database.Cursor;
-import android.net.Uri;
-
-import com.android.tv.common.flags.impl.SettableFlagsModule;
-import com.android.tv.data.ProgramImpl;
-import com.android.tv.data.api.Program;
-import com.android.tv.perf.PerformanceMonitor;
-import com.android.tv.perf.stub.StubPerformanceMonitor;
-import com.android.tv.search.LocalSearchProvider.SearchResult;
-import com.android.tv.search.LocalSearchProviderTest.TestAppComponent.TestAppModule;
-import com.android.tv.testing.TestSingletonApp;
-import com.android.tv.testing.constants.ConfigConstants;
-import com.android.tv.testing.robo.ContentProviders;
-
-import dagger.Component;
-import dagger.Module;
-import dagger.Provides;
-import dagger.android.AndroidInjectionModule;
-import dagger.android.AndroidInjector;
-import dagger.android.DispatchingAndroidInjector;
-import dagger.android.HasAndroidInjector;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-/** Unit test for {@link LocalSearchProvider}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK, application = LocalSearchProviderTest.TestApp.class)
-public class LocalSearchProviderTest {
-
-    /** Test app for {@link LocalSearchProviderTest} */
-    public static class TestApp extends TestSingletonApp implements HasAndroidInjector {
-        @Inject DispatchingAndroidInjector<Object> mDispatchingAndroidProvider;
-
-        @Override
-        public void onCreate() {
-            super.onCreate();
-            DaggerLocalSearchProviderTest_TestAppComponent.builder()
-                    .settableFlagsModule(flagsModule)
-                    .build()
-                    .inject(this);
-        }
-
-        @Override
-        public AndroidInjector<Object> androidInjector() {
-            return mDispatchingAndroidProvider;
-        }
-    }
-
-    @Component(
-            modules = {
-                AndroidInjectionModule.class,
-                SettableFlagsModule.class,
-                LocalSearchProvider.Module.class,
-                TestAppModule.class
-            })
-    @Singleton
-    interface TestAppComponent extends AndroidInjector<TestApp> {
-        @Module
-        abstract static class TestAppModule {
-            @Provides
-            @Singleton
-            static PerformanceMonitor providePerformanceMonitor() {
-                return new StubPerformanceMonitor();
-            }
-        }
-    }
-
-    private final Program mProgram1 =
-            new ProgramImpl.Builder()
-                    .setTitle("Dummy program")
-                    .setDescription("Dummy program season 2")
-                    .setPosterArtUri("FakeUri")
-                    .setStartTimeUtcMillis(1516674000000L)
-                    .setEndTimeUtcMillis(1516677000000L)
-                    .setChannelId(7)
-                    .setVideoWidth(1080)
-                    .setVideoHeight(960)
-                    .build();
-
-    private final String mAuthority = "com.android.tv.search";
-    private final String mKeyword = "mKeyword";
-    private final Uri mBaseSearchUri =
-            Uri.parse(
-                    "content://"
-                            + mAuthority
-                            + "/"
-                            + SearchManager.SUGGEST_URI_PATH_QUERY
-                            + "/"
-                            + mKeyword);
-
-    private final Uri mWrongSearchUri =
-            Uri.parse("content://" + mAuthority + "/wrong_path/" + mKeyword);
-
-    private LocalSearchProvider mProvider;
-    private ContentResolver mContentResolver;
-
-    @Mock private SearchInterface mMockSearchInterface;
-    private final FakeSearchInterface mFakeSearchInterface = new FakeSearchInterface();
-
-    @Before
-    public void setup() {
-        MockitoAnnotations.initMocks(this);
-        mProvider = ContentProviders.register(LocalSearchProvider.class, mAuthority);
-        mContentResolver = RuntimeEnvironment.application.getContentResolver();
-    }
-
-    @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 = mContentResolver.query(mWrongSearchUri, 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) {
-        mProvider.setSearchInterface(mMockSearchInterface);
-        Uri uri = mBaseSearchUri;
-        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 = mContentResolver.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(mKeyword, expectedLimit, expectedAction);
-        reset(mMockSearchInterface);
-    }
-
-    @Test
-    public void testGetType() {
-        assertThat(mProvider.getType(mBaseSearchUri)).isEqualTo(SearchManager.SUGGEST_MIME_TYPE);
-    }
-
-    @Test
-    public void query_empty() {
-        mProvider.setSearchInterface(mFakeSearchInterface);
-        Cursor cursor = mContentResolver.query(mBaseSearchUri, null, null, null, null);
-        assertThat(cursor.moveToNext()).isFalse();
-    }
-
-    @Test
-    public void query_program1() {
-        mProvider.setSearchInterface(mFakeSearchInterface);
-        mFakeSearchInterface.mPrograms.add(mProgram1);
-        Uri uri =
-                Uri.parse(
-                        "content://"
-                                + mAuthority
-                                + "/"
-                                + SearchManager.SUGGEST_URI_PATH_QUERY
-                                + "/"
-                                + "Dummy");
-        Cursor cursor = mContentResolver.query(uri, null, null, null, null);
-        assertThat(fromCursor(cursor)).containsExactly(FakeSearchInterface.fromProgram(mProgram1));
-    }
-
-    private List<SearchResult> fromCursor(Cursor cursor) {
-        List<SearchResult> results = new ArrayList<>();
-        while (cursor.moveToNext()) {
-            SearchResult.Builder result = SearchResult.builder();
-            int i = 0;
-            result.setTitle(cursor.getString(i++));
-            result.setDescription(cursor.getString(i++));
-            result.setImageUri(cursor.getString(i++));
-            result.setIntentAction(cursor.getString(i++));
-            String intentData = cursor.getString(i++);
-            result.setIntentData(intentData);
-            result.setIntentExtraData(cursor.getString(i++));
-            result.setContentType(cursor.getString(i++));
-            result.setIsLive(cursor.getString(i++).equals("1"));
-            result.setVideoWidth(Integer.valueOf(cursor.getString(i++)));
-            result.setVideoHeight(Integer.valueOf(cursor.getString(i++)));
-            result.setDuration(Long.valueOf(cursor.getString(i++)));
-            result.setProgressPercentage(Integer.valueOf(cursor.getString(i)));
-            result.setChannelId(ContentUris.parseId(Uri.parse(intentData)));
-            results.add(result.build());
-        }
-        return results;
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/testing/TvRobolectricTestRunner.java b/tests/robotests/src/com/android/tv/testing/TvRobolectricTestRunner.java
deleted file mode 100644
index 445fab2..0000000
--- a/tests/robotests/src/com/android/tv/testing/TvRobolectricTestRunner.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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.testing;
-
-import org.junit.runners.model.InitializationError;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-import org.robolectric.manifest.AndroidManifest;
-import org.robolectric.res.Fs;
-import org.robolectric.res.ResourcePath;
-
-import java.util.List;
-
-/**
- * Custom test runner TV. This is needed because the default behavior for robolectric is just to
- * grab the resource directory in the target package. We want to override this to add several
- * spanning different projects.
- *
- * <p><b>Note</b> copied from
- * http://cs/android/packages/apps/Settings/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java
- */
-public class TvRobolectricTestRunner extends RobolectricTestRunner {
-
-    /** We don't actually want to change this behavior, so we just call super. */
-    public TvRobolectricTestRunner(Class<?> testClass) throws InitializationError {
-        super(testClass);
-    }
-
-    /**
-     * We are going to create our own custom manifest so that we can add multiple resource paths to
-     * it. This lets us access resources in both Settings and SettingsLib in our tests.
-     */
-    @Override
-    protected AndroidManifest getAppManifest(Config config) {
-        final String packageName = "com.android.tv";
-
-        // By adding any resources from libraries we need the AndroidManifest, we can access
-        // them from within the parallel universe's resource loader.
-        return new AndroidManifest(
-                Fs.fileFromPath(config.manifest()),
-                Fs.fileFromPath(config.resourceDir()),
-                Fs.fileFromPath(config.assetDir()),
-                packageName) {
-            @Override
-            public List<ResourcePath> getIncludedResourcePaths() {
-                List<ResourcePath> paths = super.getIncludedResourcePaths();
-                TvRobolectricTestRunner.getIncludedResourcePaths(paths);
-                return paths;
-            }
-        };
-    }
-
-    public static void getIncludedResourcePaths(List<ResourcePath> paths) {
-        paths.add(
-                new ResourcePath(
-                        null,
-                        Fs.fileFromPath("./packages/apps/TV/res"),
-                        null));
-        paths.add(
-                new ResourcePath(
-                        null,
-                        Fs.fileFromPath("./packages/apps/TV/common/res"),
-                        null));
-        paths.add(
-                new ResourcePath(
-                        null,
-                        Fs.fileFromPath("./packages/apps/TV/material_res"),
-                        null));
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/ui/ChannelBannerViewTest.java b/tests/robotests/src/com/android/tv/ui/ChannelBannerViewTest.java
deleted file mode 100644
index 80a50f6..0000000
--- a/tests/robotests/src/com/android/tv/ui/ChannelBannerViewTest.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.tv.ui;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.robolectric.Shadows.shadowOf;
-
-import android.app.Activity;
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.ImageView;
-
-import com.android.tv.R;
-import com.android.tv.common.flags.impl.DefaultLegacyFlags;
-import com.android.tv.common.singletons.HasSingletons;
-import com.android.tv.data.api.Channel;
-import com.android.tv.data.api.Program;
-import com.android.tv.dvr.DvrManager;
-import com.android.tv.testing.TvRobolectricTestRunner;
-import com.android.tv.testing.constants.ConfigConstants;
-import com.android.tv.ui.ChannelBannerView.MySingletons;
-import com.android.tv.util.TvInputManagerHelper;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.Robolectric;
-import org.robolectric.annotation.Config;
-
-import javax.inject.Provider;
-
-/** Tests for {@link ChannelBannerView}. */
-@RunWith(TvRobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-public class ChannelBannerViewTest {
-
-    private TestActivity testActivity;
-    private ChannelBannerView mChannelBannerView;
-    private ImageView mChannelSignalStrengthView;
-
-    @Before
-    public void setUp() {
-        testActivity = Robolectric.buildActivity(TestActivity.class).create().get();
-        mChannelBannerView =
-                (ChannelBannerView)
-                        LayoutInflater.from(testActivity).inflate(R.layout.channel_banner, null);
-        mChannelSignalStrengthView = mChannelBannerView.findViewById(R.id.channel_signal_strength);
-    }
-
-    @Test
-    public void updateChannelSignalStrengthView_valueIsNotValid() {
-        mChannelBannerView.updateChannelSignalStrengthView(-1);
-        assertThat(mChannelSignalStrengthView.getVisibility()).isEqualTo(View.GONE);
-        mChannelBannerView.updateChannelSignalStrengthView(101);
-        assertThat(mChannelSignalStrengthView.getVisibility()).isEqualTo(View.GONE);
-    }
-
-    @Test
-    public void updateChannelSignalStrengthView_20() {
-        mChannelBannerView.updateChannelSignalStrengthView(20);
-        assertThat(mChannelSignalStrengthView.getVisibility()).isEqualTo(View.VISIBLE);
-        assertThat(shadowOf(mChannelSignalStrengthView.getDrawable()).getCreatedFromResId())
-                .isEqualTo(R.drawable.quantum_ic_signal_cellular_0_bar_white_24);
-    }
-
-    @Test
-    public void updateChannelSignalStrengthView_40() {
-        mChannelBannerView.updateChannelSignalStrengthView(40);
-        assertThat(mChannelSignalStrengthView.getVisibility()).isEqualTo(View.VISIBLE);
-        assertThat(shadowOf(mChannelSignalStrengthView.getDrawable()).getCreatedFromResId())
-                .isEqualTo(R.drawable.quantum_ic_signal_cellular_1_bar_white_24);
-    }
-
-    @Test
-    public void updateChannelSignalStrengthView_60() {
-        mChannelBannerView.updateChannelSignalStrengthView(60);
-        assertThat(mChannelSignalStrengthView.getVisibility()).isEqualTo(View.VISIBLE);
-        assertThat(shadowOf(mChannelSignalStrengthView.getDrawable()).getCreatedFromResId())
-                .isEqualTo(R.drawable.quantum_ic_signal_cellular_2_bar_white_24);
-    }
-
-    @Test
-    public void updateChannelSignalStrengthView_80() {
-        mChannelBannerView.updateChannelSignalStrengthView(80);
-        assertThat(mChannelSignalStrengthView.getVisibility()).isEqualTo(View.VISIBLE);
-        assertThat(shadowOf(mChannelSignalStrengthView.getDrawable()).getCreatedFromResId())
-                .isEqualTo(R.drawable.quantum_ic_signal_cellular_3_bar_white_24);
-    }
-
-    @Test
-    public void updateChannelSignalStrengthView_100() {
-        mChannelBannerView.updateChannelSignalStrengthView(100);
-        assertThat(mChannelSignalStrengthView.getVisibility()).isEqualTo(View.VISIBLE);
-        assertThat(shadowOf(mChannelSignalStrengthView.getDrawable()).getCreatedFromResId())
-                .isEqualTo(R.drawable.quantum_ic_signal_cellular_4_bar_white_24);
-    }
-
-    /** An activity for {@link ChannelBannerViewTest}. */
-    public static class TestActivity extends Activity implements HasSingletons<MySingletons> {
-
-        MySingletonsImpl mSingletons = new MySingletonsImpl();
-        Context mContext = this;
-
-        @Override
-        public ChannelBannerView.MySingletons singletons() {
-            return mSingletons;
-        }
-
-        /** MySingletons implementation needed for this class. */
-        public class MySingletonsImpl implements ChannelBannerView.MySingletons {
-
-            @Override
-            public Provider<Channel> getCurrentChannelProvider() {
-                return null;
-            }
-
-            @Override
-            public Provider<Program> getCurrentProgramProvider() {
-                return null;
-            }
-
-            @Override
-            public Provider<TvOverlayManager> getOverlayManagerProvider() {
-                return null;
-            }
-
-            @Override
-            public TvInputManagerHelper getTvInputManagerHelperSingleton() {
-                return new TvInputManagerHelper(mContext, DefaultLegacyFlags.DEFAULT);
-            }
-
-            @Override
-            public Provider<Long> getCurrentPlayingPositionProvider() {
-                return null;
-            }
-
-            @Override
-            public DvrManager getDvrManagerSingleton() {
-                return null;
-            }
-        }
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/ui/hideable/AutoHideSchedulerTest.java b/tests/robotests/src/com/android/tv/ui/hideable/AutoHideSchedulerTest.java
deleted file mode 100644
index a0a2107..0000000
--- a/tests/robotests/src/com/android/tv/ui/hideable/AutoHideSchedulerTest.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2018 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.hideable;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import com.android.tv.testing.constants.ConfigConstants;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowLooper;
-
-import java.util.concurrent.TimeUnit;
-
-/** Test for {@link AutoHideScheduler}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-public class AutoHideSchedulerTest {
-
-    private TestRunnable mTestRunnable = new TestRunnable();
-    private AutoHideScheduler mAutoHideScheduler;
-    private ShadowLooper mShadowLooper;
-
-    @Before
-    public void setUp() throws Exception {
-        mShadowLooper = ShadowLooper.getShadowMainLooper();
-        mAutoHideScheduler = new AutoHideScheduler(RuntimeEnvironment.application, mTestRunnable);
-    }
-
-    @Test
-    public void initialState() {
-        assertThat(mAutoHideScheduler.isScheduled()).isFalse();
-    }
-
-    @Test
-    public void cancel() {
-        mAutoHideScheduler.cancel();
-        assertThat(mAutoHideScheduler.isScheduled()).isFalse();
-    }
-
-    @Test
-    public void schedule() {
-        mAutoHideScheduler.schedule(10);
-        assertThat(mAutoHideScheduler.isScheduled()).isTrue();
-        assertThat(mTestRunnable.runCount).isEqualTo(0);
-    }
-
-    @Test
-    public void setA11yEnabledThenSchedule() {
-        mAutoHideScheduler.onAccessibilityStateChanged(true);
-        mAutoHideScheduler.schedule(10);
-        assertThat(mAutoHideScheduler.isScheduled()).isFalse();
-        assertThat(mTestRunnable.runCount).isEqualTo(0);
-    }
-
-    @Test
-    public void scheduleThenCancel() {
-        mAutoHideScheduler.schedule(10);
-        assertThat(mAutoHideScheduler.isScheduled()).isTrue();
-        mAutoHideScheduler.cancel();
-        assertThat(mAutoHideScheduler.isScheduled()).isFalse();
-        assertThat(mTestRunnable.runCount).isEqualTo(0);
-    }
-
-    @Test
-    public void scheduleThenLoop() {
-        mAutoHideScheduler.schedule(10);
-        assertThat(mAutoHideScheduler.isScheduled()).isTrue();
-        assertThat(mTestRunnable.runCount).isEqualTo(0);
-        mShadowLooper.idle(9, TimeUnit.MILLISECONDS);
-        assertThat(mAutoHideScheduler.isScheduled()).isTrue();
-        assertThat(mTestRunnable.runCount).isEqualTo(0);
-        mShadowLooper.idle(1, TimeUnit.MILLISECONDS);
-        assertThat(mAutoHideScheduler.isScheduled()).isFalse();
-        assertThat(mTestRunnable.runCount).isEqualTo(1);
-    }
-
-    @Test
-    public void scheduleSetA11yEnabledThenLoop() {
-        mAutoHideScheduler.schedule(10);
-        assertThat(mAutoHideScheduler.isScheduled()).isTrue();
-        assertThat(mTestRunnable.runCount).isEqualTo(0);
-        mShadowLooper.idle(9, TimeUnit.MILLISECONDS);
-        assertThat(mAutoHideScheduler.isScheduled()).isTrue();
-        assertThat(mTestRunnable.runCount).isEqualTo(0);
-        mAutoHideScheduler.onAccessibilityStateChanged(true);
-        mShadowLooper.idle(1, TimeUnit.MILLISECONDS);
-        assertThat(mAutoHideScheduler.isScheduled()).isFalse();
-        assertThat(mTestRunnable.runCount).isEqualTo(0);
-    }
-
-    private static class TestRunnable implements Runnable {
-        int runCount = 0;
-
-        @Override
-        public void run() {
-            runCount++;
-        }
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/util/MultiLongSparseArrayTest.java b/tests/robotests/src/com/android/tv/util/MultiLongSparseArrayTest.java
deleted file mode 100644
index 931ff0b..0000000
--- a/tests/robotests/src/com/android/tv/util/MultiLongSparseArrayTest.java
+++ /dev/null
@@ -1,105 +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 static com.google.common.truth.Truth.assertThat;
-
-import com.android.tv.testing.constants.ConfigConstants;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-/** Tests for {@link MultiLongSparseArray}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-public class MultiLongSparseArrayTest {
-    @Test
-    public void testEmpty() {
-        MultiLongSparseArray<String> sparseArray = new MultiLongSparseArray<>();
-        assertThat(sparseArray.get(0)).isEmpty();
-    }
-
-    @Test
-    public void testOneElement() {
-        MultiLongSparseArray<String> sparseArray = new MultiLongSparseArray<>();
-        sparseArray.put(0, "foo");
-        assertThat(sparseArray.get(0)).containsExactly("foo");
-    }
-
-    @Test
-    public void testTwoElements() {
-        MultiLongSparseArray<String> sparseArray = new MultiLongSparseArray<>();
-        sparseArray.put(0, "foo");
-        sparseArray.put(0, "bar");
-        assertThat(sparseArray.get(0)).containsExactly("foo", "bar");
-    }
-
-    @Test
-    public void testClearEmptyCache() {
-        MultiLongSparseArray<String> sparseArray = new MultiLongSparseArray<>();
-        sparseArray.clearEmptyCache();
-        assertThat(sparseArray.getEmptyCacheSize()).isEqualTo(0);
-        sparseArray.put(0, "foo");
-        sparseArray.remove(0, "foo");
-        assertThat(sparseArray.getEmptyCacheSize()).isEqualTo(1);
-        sparseArray.clearEmptyCache();
-        assertThat(sparseArray.getEmptyCacheSize()).isEqualTo(0);
-    }
-
-    @Test
-    public void testMaxEmptyCacheSize() {
-        MultiLongSparseArray<String> sparseArray = new MultiLongSparseArray<>();
-        sparseArray.clearEmptyCache();
-        assertThat(sparseArray.getEmptyCacheSize()).isEqualTo(0);
-        for (int i = 0; i <= MultiLongSparseArray.DEFAULT_MAX_EMPTIES_KEPT + 2; i++) {
-            sparseArray.put(i, "foo");
-        }
-        for (int i = 0; i <= MultiLongSparseArray.DEFAULT_MAX_EMPTIES_KEPT + 2; i++) {
-            sparseArray.remove(i, "foo");
-        }
-        assertThat(sparseArray.getEmptyCacheSize())
-                .isEqualTo(MultiLongSparseArray.DEFAULT_MAX_EMPTIES_KEPT);
-        sparseArray.clearEmptyCache();
-        assertThat(sparseArray.getEmptyCacheSize()).isEqualTo(0);
-    }
-
-    @Test
-    public void testReuseEmptySets() {
-        MultiLongSparseArray<String> sparseArray = new MultiLongSparseArray<>();
-        sparseArray.clearEmptyCache();
-        assertThat(sparseArray.getEmptyCacheSize()).isEqualTo(0);
-        // create a bunch of sets
-        for (int i = 0; i <= MultiLongSparseArray.DEFAULT_MAX_EMPTIES_KEPT + 2; i++) {
-            sparseArray.put(i, "foo");
-        }
-        // remove them so they are all put in the cache.
-        for (int i = 0; i <= MultiLongSparseArray.DEFAULT_MAX_EMPTIES_KEPT + 2; i++) {
-            sparseArray.remove(i, "foo");
-        }
-        assertThat(sparseArray.getEmptyCacheSize())
-                .isEqualTo(MultiLongSparseArray.DEFAULT_MAX_EMPTIES_KEPT);
-
-        // now create elements, that use the cached empty sets.
-        for (int i = 0; i < MultiLongSparseArray.DEFAULT_MAX_EMPTIES_KEPT; i++) {
-            sparseArray.put(10 + i, "bar");
-            assertThat(sparseArray.getEmptyCacheSize())
-                    .isEqualTo(MultiLongSparseArray.DEFAULT_MAX_EMPTIES_KEPT - i - 1);
-        }
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/util/TvInputManagerHelperRoboTest.java b/tests/robotests/src/com/android/tv/util/TvInputManagerHelperRoboTest.java
deleted file mode 100644
index 9586c1f..0000000
--- a/tests/robotests/src/com/android/tv/util/TvInputManagerHelperRoboTest.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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 static com.google.common.truth.Truth.assertThat;
-
-import android.media.tv.TvInputInfo;
-import android.media.tv.TvInputManager;
-
-import com.android.tv.common.flags.impl.DefaultLegacyFlags;
-import com.android.tv.testing.constants.ConfigConstants;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-/**
- * Tests for {@link TvInputManagerHelper}.
- *
- * <p>This test is named ...RoboTest because there is already a test named <code>
- * TvInputManagerHelperTest</code>
- */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-public class TvInputManagerHelperRoboTest {
-
-    @Test
-    public void getInputState_null() {
-        TvInputInfo tvinputInfo = null;
-        TvInputManagerHelper tvInputManagerHelper =
-                new TvInputManagerHelper(
-                        RuntimeEnvironment.application, DefaultLegacyFlags.DEFAULT);
-        assertThat(TvInputManager.INPUT_STATE_DISCONNECTED)
-                .isSameInstanceAs(tvInputManagerHelper.getInputState(tvinputInfo));
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/util/TvProviderUtilsTest.java b/tests/robotests/src/com/android/tv/util/TvProviderUtilsTest.java
deleted file mode 100644
index bd0e996..0000000
--- a/tests/robotests/src/com/android/tv/util/TvProviderUtilsTest.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2018 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 static com.google.common.truth.Truth.assertThat;
-
-import android.content.pm.ProviderInfo;
-import android.media.tv.TvContract;
-import android.os.Bundle;
-
-import com.android.tv.testing.constants.ConfigConstants;
-import com.android.tv.testing.fakes.FakeTvProvider;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.Robolectric;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowContentResolver;
-
-import java.util.Set;
-
-/** Tests for {@link TvProviderUtils}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(
-        sdk = ConfigConstants.SDK,
-        shadows = {ShadowContentResolver.class})
-public class TvProviderUtilsTest {
-
-    @Before
-    public void setUp() {
-        ProviderInfo info = new ProviderInfo();
-        info.authority = TvContract.AUTHORITY;
-        FakeTvProvider provider =
-                Robolectric.buildContentProvider(FakeTvProviderForTesting.class).create(info).get();
-        provider.onCreate();
-        ShadowContentResolver.registerProviderInternal(TvContract.AUTHORITY, provider);
-    }
-
-    @Test
-    public void testAddExtraColumnsToProjection() {
-        String[] inputStrings = {"column_1", "column_2", "column_3"};
-        assertThat(
-                        TvProviderUtils.addExtraColumnsToProjection(
-                                inputStrings, TvProviderUtils.EXTRA_PROGRAM_COLUMN_STATE))
-                .asList()
-                .containsExactly(
-                        "column_1",
-                        "column_2",
-                        "column_3",
-                        TvProviderUtils.EXTRA_PROGRAM_COLUMN_STATE)
-                .inOrder();
-    }
-
-    @Test
-    public void testAddExtraColumnsToProjection_extraColumnExists() {
-        String[] inputStrings = {
-            "column_1",
-            "column_2",
-            TvProviderUtils.EXTRA_PROGRAM_COLUMN_SERIES_ID,
-            TvProviderUtils.EXTRA_PROGRAM_COLUMN_STATE,
-            "column_3"
-        };
-        assertThat(
-                        TvProviderUtils.addExtraColumnsToProjection(
-                                inputStrings, TvProviderUtils.EXTRA_PROGRAM_COLUMN_STATE))
-                .asList()
-                .containsExactly(
-                        "column_1",
-                        "column_2",
-                        TvProviderUtils.EXTRA_PROGRAM_COLUMN_SERIES_ID,
-                        TvProviderUtils.EXTRA_PROGRAM_COLUMN_STATE,
-                        "column_3")
-                .inOrder();
-    }
-
-    @Test
-    public void testGetExistingColumns_noException() {
-        FakeTvProviderForTesting.mThrowException = false;
-        FakeTvProviderForTesting.mBundleResult = new Bundle();
-        FakeTvProviderForTesting.mBundleResult.putStringArray(
-                TvContract.EXTRA_EXISTING_COLUMN_NAMES, new String[] {"column 1", "column 2"});
-        Set<String> columns =
-                TvProviderUtils.getExistingColumns(
-                        RuntimeEnvironment.application, TvContract.Programs.CONTENT_URI);
-        assertThat(columns).containsExactly("column 1", "column 2");
-    }
-
-    @Test
-    public void testGetExistingColumns_throwsException() {
-        FakeTvProviderForTesting.mThrowException = true;
-        FakeTvProviderForTesting.mBundleResult = new Bundle();
-        // should be no exception here
-        Set<String> columns =
-                TvProviderUtils.getExistingColumns(
-                        RuntimeEnvironment.application, TvContract.Programs.CONTENT_URI);
-        assertThat(columns).isEmpty();
-    }
-
-    private static class FakeTvProviderForTesting extends FakeTvProvider {
-        private static Bundle mBundleResult;
-        private static boolean mThrowException;
-
-        @Override
-        public Bundle call(String method, String arg, Bundle extras) {
-            if (mThrowException) {
-                throw new IllegalStateException();
-            }
-            return mBundleResult;
-        }
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/util/TvTrackInfoUtilsTest.java b/tests/robotests/src/com/android/tv/util/TvTrackInfoUtilsTest.java
deleted file mode 100644
index c59cb16..0000000
--- a/tests/robotests/src/com/android/tv/util/TvTrackInfoUtilsTest.java
+++ /dev/null
@@ -1,385 +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 static com.android.tv.util.TvTrackInfoUtils.getBestTrackInfo;
-
-import static com.google.common.truth.Truth.assertWithMessage;
-
-import static org.junit.Assert.assertEquals;
-
-import android.media.tv.TvTrackInfo;
-import android.os.Build.VERSION_CODES;
-import android.os.LocaleList;
-
-import com.android.tv.testing.ComparatorTester;
-import com.android.tv.testing.TvRobolectricTestRunner;
-import com.android.tv.testing.constants.ConfigConstants;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Locale;
-
-/** Tests for {@link com.android.tv.util.TvTrackInfoUtils}. */
-@RunWith(TvRobolectricTestRunner.class)
-@Config(minSdk = ConfigConstants.MIN_SDK, maxSdk = ConfigConstants.MAX_SDK)
-public class TvTrackInfoUtilsTest {
-
-    /** Tests for {@link TvTrackInfoUtils#getBestTrackInfo}. */
-    private static final String UN_MATCHED_ID = "no matching ID";
-
-    private final TvTrackInfo info1En1 = createTvTrackInfo("track_1", "en", 1);
-
-    private final TvTrackInfo info2En5 = createTvTrackInfo("track_2", "en", 5);
-
-    private final TvTrackInfo info3Fr8 = createTvTrackInfo("track_3", "fr", 8);
-
-    private final TvTrackInfo info4Null2 = createTvTrackInfo("track_4", null, 2);
-
-    private final TvTrackInfo info5Null6 = createTvTrackInfo("track_5", null, 6);
-
-    private TvTrackInfo createTvTrackInfo(String trackId, String language, int audioChannelCount) {
-        return new TvTrackInfo.Builder(TvTrackInfo.TYPE_AUDIO, trackId)
-                .setLanguage(language)
-                .setAudioChannelCount(audioChannelCount)
-                .build();
-    }
-
-    private final List<TvTrackInfo> allTracks =
-            Arrays.asList(info1En1, info2En5, info3Fr8, info4Null2, info5Null6);
-    private final List<TvTrackInfo> nullLanguageTracks = Arrays.asList(info4Null2, info5Null6);
-
-    @Test
-    public void testGetBestTrackInfo_empty() {
-        TvTrackInfo result = getBestTrackInfo(Collections.emptyList(), UN_MATCHED_ID, "en", 1);
-        assertWithMessage("best track ").that(result).isEqualTo(null);
-    }
-
-    @Test
-    public void testGetBestTrackInfo_exactMatch() {
-        TvTrackInfo result = getBestTrackInfo(allTracks, "track_1", "en", 1);
-        assertWithMessage("best track ").that(result).isEqualTo(info1En1);
-    }
-
-    @Test
-    public void testGetBestTrackInfo_langAndChannelCountMatch() {
-        TvTrackInfo result = getBestTrackInfo(allTracks, UN_MATCHED_ID, "en", 5);
-        assertWithMessage("best track ").that(result).isEqualTo(info2En5);
-    }
-
-    @Test
-    public void testGetBestTrackInfo_languageOnlyMatch() {
-        TvTrackInfo result = getBestTrackInfo(allTracks, UN_MATCHED_ID, "fr", 1);
-        assertWithMessage("best track ").that(result).isEqualTo(info3Fr8);
-    }
-
-    @Test
-    @Config(minSdk = ConfigConstants.MIN_SDK, maxSdk = VERSION_CODES.M)
-    public void testGetBestTrackInfo_channelCountOnlyMatchWithNullLanguage_23() {
-        Locale localPreference = Locale.forLanguageTag("es");
-        Locale.setDefault(localPreference);
-        TvTrackInfo result = getBestTrackInfo(allTracks, UN_MATCHED_ID, null, 8);
-        assertWithMessage("best track ").that(result).isEqualTo(info3Fr8);
-    }
-
-    @Test
-    @Config(minSdk = VERSION_CODES.N, maxSdk = ConfigConstants.MAX_SDK)
-    public void testGetBestTrackInfo_channelCountOnlyMatchWithNullLanguage() {
-        // Setting LoacaleList to a language which is not in the test set.
-        LocaleList localPreferenceList = LocaleList.forLanguageTags("es");
-        LocaleList.setDefault(localPreferenceList);
-        TvTrackInfo result = getBestTrackInfo(allTracks, UN_MATCHED_ID, null, 8);
-        assertWithMessage("best track ").that(result).isEqualTo(info3Fr8);
-    }
-
-    @Test
-    public void testGetBestTrackInfo_noMatches() {
-        TvTrackInfo result = getBestTrackInfo(allTracks, UN_MATCHED_ID, "kr", 1);
-        assertWithMessage("best track ").that(result).isEqualTo(info1En1);
-    }
-
-    @Test
-    @Config(minSdk = ConfigConstants.MIN_SDK, maxSdk = VERSION_CODES.M)
-    public void testGetBestTrackInfo_noMatchesWithNullLanguage_23() {
-        Locale localPreference = Locale.forLanguageTag("es");
-        Locale.setDefault(localPreference);
-        TvTrackInfo result = getBestTrackInfo(allTracks, UN_MATCHED_ID, null, 0);
-        assertWithMessage("best track ").that(result).isEqualTo(info3Fr8);
-    }
-
-    @Test
-    @Config(minSdk = VERSION_CODES.N, maxSdk = ConfigConstants.MAX_SDK)
-    public void testGetBestTrackInfo_noMatchesWithNullLanguage() {
-        // Setting LoacaleList to a language which is not in the test set.
-        LocaleList localPreferenceList = LocaleList.forLanguageTags("es");
-        LocaleList.setDefault(localPreferenceList);
-        TvTrackInfo result = getBestTrackInfo(allTracks, UN_MATCHED_ID, null, 0);
-        assertWithMessage("best track ").that(result).isEqualTo(info3Fr8);
-    }
-
-    @Test
-    public void testGetBestTrackInfo_channelCountAndIdMatch() {
-        TvTrackInfo result = getBestTrackInfo(nullLanguageTracks, "track_5", null, 6);
-        assertWithMessage("best track ").that(result).isEqualTo(info5Null6);
-    }
-
-    @Test
-    public void testComparator() {
-        List<String> languages = Arrays.asList("en", "spa", "hi");
-        Comparator<TvTrackInfo> comparator =
-                TvTrackInfoUtils.createComparator("track_1", languages, 1);
-        new ComparatorTester(comparator)
-                .permitInconsistencyWithEquals()
-                // lang not match
-                .addEqualityGroup(
-                        createTvTrackInfo("track_1", "kr", 2),
-                        createTvTrackInfo("track_1", "ja", 2),
-                        createTvTrackInfo("track_1", "ch", 2))
-                // lang not match, better count
-                .addEqualityGroup(
-                        createTvTrackInfo("track_1", "kr", 3),
-                        createTvTrackInfo("track_1", "ch", 3))
-                // lang not match, count match
-                .addEqualityGroup(
-                        createTvTrackInfo("track_1", "ch", 1),
-                        createTvTrackInfo("track_1", "ja", 1))
-                // lang match in order of increasing priority
-                .addEqualityGroup(createTvTrackInfo("track_1", "hi", 3))
-                .addEqualityGroup(createTvTrackInfo("track_2", "hi", 7))
-                .addEqualityGroup(createTvTrackInfo("track_1", "hi", 1))
-                .addEqualityGroup(createTvTrackInfo("track_1", "spa", 5))
-                .addEqualityGroup(createTvTrackInfo("track_2", "spa", 1))
-                .addEqualityGroup(createTvTrackInfo("track_1", "spa", 1))
-                .addEqualityGroup(createTvTrackInfo("track_2", "en", 3))
-                .addEqualityGroup(
-                        createTvTrackInfo("track_1", "en", 5),
-                        createTvTrackInfo("track_2", "en", 5))
-                // best lang match and count match
-                .addEqualityGroup(
-                        createTvTrackInfo("track_2", "en", 1),
-                        createTvTrackInfo("track_3", "en", 1))
-                // all match
-                .addEqualityGroup(
-                        createTvTrackInfo("track_1", "en", 1),
-                        createTvTrackInfo("track_1", "en", 1))
-                .testCompare();
-    }
-
-    /** Tests for {@link TvTrackInfoUtils#needToShowSampleRate}. */
-    private final TvTrackInfo info6En1 = createTvTrackInfo("track_6", "en", 1);
-
-    private final TvTrackInfo info7En0 = createTvTrackInfo("track_7", "en", 0);
-
-    private final TvTrackInfo info8En0 = createTvTrackInfo("track_8", "en", 0);
-
-    private List<TvTrackInfo> trackList;
-
-    @Test
-    public void needToShowSampleRate_false() {
-        trackList = Arrays.asList(info1En1, info2En5);
-        assertEquals(
-                false,
-                TvTrackInfoUtils.needToShowSampleRate(RuntimeEnvironment.application, trackList));
-    }
-
-    @Test
-    public void needToShowSampleRate_sameLanguageAndChannelCount() {
-        trackList = Arrays.asList(info1En1, info6En1);
-        assertEquals(
-                true,
-                TvTrackInfoUtils.needToShowSampleRate(RuntimeEnvironment.application, trackList));
-    }
-
-    @Test
-    public void needToShowSampleRate_sameLanguageNoChannelCount() {
-        trackList = Arrays.asList(info7En0, info8En0);
-        assertEquals(
-                true,
-                TvTrackInfoUtils.needToShowSampleRate(RuntimeEnvironment.application, trackList));
-    }
-
-    /** Tests for {@link TvTrackInfoUtils#getMultiAudioString}. */
-    private static final String TRACK_ID = "test_track_id";
-
-    private static final int AUDIO_SAMPLE_RATE = 48000;
-
-    @Test
-    public void testAudioTrackLanguage() {
-        assertEquals(
-                "Korean",
-                TvTrackInfoUtils.getMultiAudioString(
-                        RuntimeEnvironment.application, createAudioTrackInfo("kor"), false));
-        assertEquals(
-                "English",
-                TvTrackInfoUtils.getMultiAudioString(
-                        RuntimeEnvironment.application, createAudioTrackInfo("eng"), false));
-        assertEquals(
-                "Unknown language",
-                TvTrackInfoUtils.getMultiAudioString(
-                        RuntimeEnvironment.application, createAudioTrackInfo(null), false));
-        assertEquals(
-                "Unknown language",
-                TvTrackInfoUtils.getMultiAudioString(
-                        RuntimeEnvironment.application, createAudioTrackInfo(""), false));
-        assertEquals(
-                "abc",
-                TvTrackInfoUtils.getMultiAudioString(
-                        RuntimeEnvironment.application, createAudioTrackInfo("abc"), false));
-    }
-
-    @Test
-    public void testAudioTrackCount() {
-        assertEquals(
-                "English",
-                TvTrackInfoUtils.getMultiAudioString(
-                        RuntimeEnvironment.application, createAudioTrackInfo("eng", -1), false));
-        assertEquals(
-                "English",
-                TvTrackInfoUtils.getMultiAudioString(
-                        RuntimeEnvironment.application, createAudioTrackInfo("eng", 0), false));
-        assertEquals(
-                "English (mono)",
-                TvTrackInfoUtils.getMultiAudioString(
-                        RuntimeEnvironment.application, createAudioTrackInfo("eng", 1), false));
-        assertEquals(
-                "English (stereo)",
-                TvTrackInfoUtils.getMultiAudioString(
-                        RuntimeEnvironment.application, createAudioTrackInfo("eng", 2), false));
-        assertEquals(
-                "English (3 channels)",
-                TvTrackInfoUtils.getMultiAudioString(
-                        RuntimeEnvironment.application, createAudioTrackInfo("eng", 3), false));
-        assertEquals(
-                "English (4 channels)",
-                TvTrackInfoUtils.getMultiAudioString(
-                        RuntimeEnvironment.application, createAudioTrackInfo("eng", 4), false));
-        assertEquals(
-                "English (5 channels)",
-                TvTrackInfoUtils.getMultiAudioString(
-                        RuntimeEnvironment.application, createAudioTrackInfo("eng", 5), false));
-        assertEquals(
-                "English (5.1 surround)",
-                TvTrackInfoUtils.getMultiAudioString(
-                        RuntimeEnvironment.application, createAudioTrackInfo("eng", 6), false));
-        assertEquals(
-                "English (7 channels)",
-                TvTrackInfoUtils.getMultiAudioString(
-                        RuntimeEnvironment.application, createAudioTrackInfo("eng", 7), false));
-        assertEquals(
-                "English (7.1 surround)",
-                TvTrackInfoUtils.getMultiAudioString(
-                        RuntimeEnvironment.application, createAudioTrackInfo("eng", 8), false));
-    }
-
-    @Test
-    public void testShowSampleRate() {
-        assertEquals(
-                "Korean (48kHz)",
-                TvTrackInfoUtils.getMultiAudioString(
-                        RuntimeEnvironment.application, createAudioTrackInfo("kor", 0), true));
-        assertEquals(
-                "Korean (7.1 surround, 48kHz)",
-                TvTrackInfoUtils.getMultiAudioString(
-                        RuntimeEnvironment.application, createAudioTrackInfo("kor", 8), true));
-    }
-
-    private static TvTrackInfo createAudioTrackInfo(String language) {
-        return createAudioTrackInfo(language, 0);
-    }
-
-    private static TvTrackInfo createAudioTrackInfo(String language, int channelCount) {
-        return new TvTrackInfo.Builder(TvTrackInfo.TYPE_AUDIO, TRACK_ID)
-                .setLanguage(language)
-                .setAudioChannelCount(channelCount)
-                .setAudioSampleRate(AUDIO_SAMPLE_RATE)
-                .build();
-    }
-
-    /** Tests for {@link TvTrackInfoUtils#toString */
-    @Test
-    public void toString_audioWithDetails() {
-        assertEquals(
-                "TvTrackInfo{type=Audio, id=track_1, language=en, "
-                        + "description=test, audioChannelCount=1, audioSampleRate=5}",
-                TvTrackInfoUtils.toString(
-                        new TvTrackInfo.Builder(TvTrackInfo.TYPE_AUDIO, "track_1")
-                                .setLanguage("en")
-                                .setAudioChannelCount(1)
-                                .setDescription("test")
-                                .setAudioSampleRate(5)
-                                .build()));
-    }
-
-    @Test
-    public void toString_audioWithDefaults() {
-        assertEquals(
-                "TvTrackInfo{type=Audio, id=track_2, language=null, "
-                        + "description=null, audioChannelCount=0, audioSampleRate=0}",
-                TvTrackInfoUtils.toString(
-                        new TvTrackInfo.Builder(TvTrackInfo.TYPE_AUDIO, "track_2").build()));
-    }
-
-    @Test
-    public void toString_videoWithDetails() {
-        assertEquals(
-                "TvTrackInfo{type=Video, id=track_3, language=en, description=test, videoWidth=1,"
-                        + " videoHeight=1, videoFrameRate=1.0, videoPixelAspectRatio=2.0}",
-                TvTrackInfoUtils.toString(
-                        new TvTrackInfo.Builder(TvTrackInfo.TYPE_VIDEO, "track_3")
-                                .setLanguage("en")
-                                .setDescription("test")
-                                .setVideoWidth(1)
-                                .setVideoHeight(1)
-                                .setVideoFrameRate(1)
-                                .setVideoPixelAspectRatio(2)
-                                .build()));
-    }
-
-    @Test
-    public void toString_videoWithDefaults() {
-        assertEquals(
-                "TvTrackInfo{type=Video, id=track_4, language=null, description=null, videoWidth=0,"
-                        + " videoHeight=0, videoFrameRate=0.0, videoPixelAspectRatio=1.0}",
-                TvTrackInfoUtils.toString(
-                        new TvTrackInfo.Builder(TvTrackInfo.TYPE_VIDEO, "track_4").build()));
-    }
-
-    @Test
-    public void toString_subtitleWithDetails() {
-        assertEquals(
-                "TvTrackInfo{type=Subtitle, id=track_5, language=en, description=test}",
-                TvTrackInfoUtils.toString(
-                        new TvTrackInfo.Builder(TvTrackInfo.TYPE_SUBTITLE, "track_5")
-                                .setLanguage("en")
-                                .setDescription("test")
-                                .build()));
-    }
-
-    @Test
-    public void toString_subtitleWithDefaults() {
-        assertEquals(
-                "TvTrackInfo{type=Subtitle, id=track_6, language=null, description=null}",
-                TvTrackInfoUtils.toString(
-                        new TvTrackInfo.Builder(TvTrackInfo.TYPE_SUBTITLE, "track_6").build()));
-    }
-}
diff --git a/tests/robotests/src/com/android/tv/util/UtilsTest.java b/tests/robotests/src/com/android/tv/util/UtilsTest.java
deleted file mode 100644
index eb27e8a..0000000
--- a/tests/robotests/src/com/android/tv/util/UtilsTest.java
+++ /dev/null
@@ -1,495 +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 static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import android.text.format.DateUtils;
-
-import com.android.tv.testing.constants.ConfigConstants;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-import java.util.Calendar;
-import java.util.GregorianCalendar;
-import java.util.Locale;
-import java.util.TimeZone;
-
-/**
- * Tests for {@link com.android.tv.util.Utils#getDurationString}.
- *
- * <p>This test uses deprecated flags {@link DateUtils#FORMAT_12HOUR} and {@link
- * DateUtils#FORMAT_24HOUR} to run this test independent to system's 12/24h format.
- */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-public class UtilsTest {
-    // 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);
-
-    // All possible list for a parameter to test parameter independent result.
-    private static final boolean[] PARAM_USE_SHORT_FORMAT = {false, true};
-
-    @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. */
-    private static long getJanOfThisYearInMillis(int date, int hour, int minutes) {
-        return new GregorianCalendar(getThisYear(), Calendar.JANUARY, date, hour, minutes)
-                .getTimeInMillis();
-    }
-
-    private static long getJanOfThisYearInMillis(int date, int hour) {
-        return getJanOfThisYearInMillis(date, hour, 0);
-    }
-
-    /** Return time in millis assuming that whose year is this year and month is Feb. */
-    private static long getFebOfThisYearInMillis(int date, int hour, int minutes) {
-        return new GregorianCalendar(getThisYear(), Calendar.FEBRUARY, date, hour, minutes)
-                .getTimeInMillis();
-    }
-
-    private static long getFebOfThisYearInMillis(int date, int hour) {
-        return getFebOfThisYearInMillis(date, hour, 0);
-    }
-
-    private static int getThisYear() {
-        return new GregorianCalendar().get(GregorianCalendar.YEAR);
-    }
-
-    @Test
-    public void testSameDateAndTime() {
-        assertEquals(
-                "3:00 AM",
-                Utils.getDurationString(
-                        RuntimeEnvironment.application,
-                        DATE_THIS_YEAR_2_1_MS,
-                        getFebOfThisYearInMillis(1, 3),
-                        getFebOfThisYearInMillis(1, 3),
-                        false,
-                        DateUtils.FORMAT_12HOUR));
-        assertEquals(
-                "03:00",
-                Utils.getDurationString(
-                        RuntimeEnvironment.application,
-                        DATE_THIS_YEAR_2_1_MS,
-                        getFebOfThisYearInMillis(1, 3),
-                        getFebOfThisYearInMillis(1, 3),
-                        false,
-                        DateUtils.FORMAT_24HOUR));
-    }
-
-    @Test
-    public void testDurationWithinToday() {
-        assertEquals(
-                "12:00 – 3:00 AM",
-                Utils.getDurationString(
-                        RuntimeEnvironment.application,
-                        DATE_THIS_YEAR_2_1_MS,
-                        DATE_THIS_YEAR_2_1_MS,
-                        getFebOfThisYearInMillis(1, 3),
-                        false,
-                        DateUtils.FORMAT_12HOUR));
-        assertEquals(
-                "00:00 – 03:00",
-                Utils.getDurationString(
-                        RuntimeEnvironment.application,
-                        DATE_THIS_YEAR_2_1_MS,
-                        DATE_THIS_YEAR_2_1_MS,
-                        getFebOfThisYearInMillis(1, 3),
-                        false,
-                        DateUtils.FORMAT_24HOUR));
-    }
-
-    @Test
-    public void testDurationFromYesterdayToToday() {
-        assertEquals(
-                "Jan 31, 3:00 AM – Feb 1, 4:00 AM",
-                Utils.getDurationString(
-                        RuntimeEnvironment.application,
-                        DATE_THIS_YEAR_2_1_MS,
-                        getJanOfThisYearInMillis(31, 3),
-                        getFebOfThisYearInMillis(1, 4),
-                        false,
-                        DateUtils.FORMAT_12HOUR));
-        assertEquals(
-                "Jan 31, 03:00 – Feb 1, 04:00",
-                Utils.getDurationString(
-                        RuntimeEnvironment.application,
-                        DATE_THIS_YEAR_2_1_MS,
-                        getJanOfThisYearInMillis(31, 3),
-                        getFebOfThisYearInMillis(1, 4),
-                        false,
-                        DateUtils.FORMAT_24HOUR));
-        assertEquals(
-                "1/31, 11:30 PM – 12:30 AM",
-                Utils.getDurationString(
-                        RuntimeEnvironment.application,
-                        DATE_THIS_YEAR_2_1_MS,
-                        getJanOfThisYearInMillis(31, 23, 30),
-                        getFebOfThisYearInMillis(1, 0, 30),
-                        true,
-                        DateUtils.FORMAT_12HOUR));
-        assertEquals(
-                "1/31, 23:30 – 00:30",
-                Utils.getDurationString(
-                        RuntimeEnvironment.application,
-                        DATE_THIS_YEAR_2_1_MS,
-                        getJanOfThisYearInMillis(31, 23, 30),
-                        getFebOfThisYearInMillis(1, 0, 30),
-                        true,
-                        DateUtils.FORMAT_24HOUR));
-    }
-
-    @Test
-    public void testDurationFromTodayToTomorrow() {
-        assertEquals(
-                "Feb 1, 3:00 AM – Feb 2, 4:00 AM",
-                Utils.getDurationString(
-                        RuntimeEnvironment.application,
-                        DATE_THIS_YEAR_2_1_MS,
-                        getFebOfThisYearInMillis(1, 3),
-                        getFebOfThisYearInMillis(2, 4),
-                        false,
-                        DateUtils.FORMAT_12HOUR));
-        assertEquals(
-                "Feb 1, 03:00 – Feb 2, 04:00",
-                Utils.getDurationString(
-                        RuntimeEnvironment.application,
-                        DATE_THIS_YEAR_2_1_MS,
-                        getFebOfThisYearInMillis(1, 3),
-                        getFebOfThisYearInMillis(2, 4),
-                        false,
-                        DateUtils.FORMAT_24HOUR));
-        assertEquals(
-                "2/1, 3:00 AM – 2/2, 4:00 AM",
-                Utils.getDurationString(
-                        RuntimeEnvironment.application,
-                        DATE_THIS_YEAR_2_1_MS,
-                        getFebOfThisYearInMillis(1, 3),
-                        getFebOfThisYearInMillis(2, 4),
-                        true,
-                        DateUtils.FORMAT_12HOUR));
-        assertEquals(
-                "2/1, 03:00 – 2/2, 04:00",
-                Utils.getDurationString(
-                        RuntimeEnvironment.application,
-                        DATE_THIS_YEAR_2_1_MS,
-                        getFebOfThisYearInMillis(1, 3),
-                        getFebOfThisYearInMillis(2, 4),
-                        true,
-                        DateUtils.FORMAT_24HOUR));
-
-        assertEquals(
-                "Feb 1, 11:30 PM – Feb 2, 12:30 AM",
-                Utils.getDurationString(
-                        RuntimeEnvironment.application,
-                        DATE_THIS_YEAR_2_1_MS,
-                        getFebOfThisYearInMillis(1, 23, 30),
-                        getFebOfThisYearInMillis(2, 0, 30),
-                        false,
-                        DateUtils.FORMAT_12HOUR));
-        assertEquals(
-                "Feb 1, 23:30 – Feb 2, 00:30",
-                Utils.getDurationString(
-                        RuntimeEnvironment.application,
-                        DATE_THIS_YEAR_2_1_MS,
-                        getFebOfThisYearInMillis(1, 23, 30),
-                        getFebOfThisYearInMillis(2, 0, 30),
-                        false,
-                        DateUtils.FORMAT_24HOUR));
-        assertEquals(
-                "11:30 PM – 12:30 AM",
-                Utils.getDurationString(
-                        RuntimeEnvironment.application,
-                        DATE_THIS_YEAR_2_1_MS,
-                        getFebOfThisYearInMillis(1, 23, 30),
-                        getFebOfThisYearInMillis(2, 0, 30),
-                        true,
-                        DateUtils.FORMAT_12HOUR));
-        assertEquals(
-                "23:30 – 00:30",
-                Utils.getDurationString(
-                        RuntimeEnvironment.application,
-                        DATE_THIS_YEAR_2_1_MS,
-                        getFebOfThisYearInMillis(1, 23, 30),
-                        getFebOfThisYearInMillis(2, 0, 30),
-                        true,
-                        DateUtils.FORMAT_24HOUR));
-    }
-
-    @Test
-    public void testDurationWithinTomorrow() {
-        assertEquals(
-                "Feb 2, 2:00 – 4:00 AM",
-                Utils.getDurationString(
-                        RuntimeEnvironment.application,
-                        DATE_THIS_YEAR_2_1_MS,
-                        getFebOfThisYearInMillis(2, 2),
-                        getFebOfThisYearInMillis(2, 4),
-                        false,
-                        DateUtils.FORMAT_12HOUR));
-        assertEquals(
-                "Feb 2, 02:00 – 04:00",
-                Utils.getDurationString(
-                        RuntimeEnvironment.application,
-                        DATE_THIS_YEAR_2_1_MS,
-                        getFebOfThisYearInMillis(2, 2),
-                        getFebOfThisYearInMillis(2, 4),
-                        false,
-                        DateUtils.FORMAT_24HOUR));
-        assertEquals(
-                "2/2, 2:00 – 4:00 AM",
-                Utils.getDurationString(
-                        RuntimeEnvironment.application,
-                        DATE_THIS_YEAR_2_1_MS,
-                        getFebOfThisYearInMillis(2, 2),
-                        getFebOfThisYearInMillis(2, 4),
-                        true,
-                        DateUtils.FORMAT_12HOUR));
-        assertEquals(
-                "2/2, 02:00 – 04:00",
-                Utils.getDurationString(
-                        RuntimeEnvironment.application,
-                        DATE_THIS_YEAR_2_1_MS,
-                        getFebOfThisYearInMillis(2, 2),
-                        getFebOfThisYearInMillis(2, 4),
-                        true,
-                        DateUtils.FORMAT_24HOUR));
-    }
-
-    @Test
-    public void testStartOfDay() {
-        assertEquals(
-                "12:00 – 1:00 AM",
-                Utils.getDurationString(
-                        RuntimeEnvironment.application,
-                        DATE_THIS_YEAR_2_1_MS,
-                        DATE_THIS_YEAR_2_1_MS,
-                        getFebOfThisYearInMillis(1, 1),
-                        false,
-                        DateUtils.FORMAT_12HOUR));
-        assertEquals(
-                "00:00 – 01:00",
-                Utils.getDurationString(
-                        RuntimeEnvironment.application,
-                        DATE_THIS_YEAR_2_1_MS,
-                        DATE_THIS_YEAR_2_1_MS,
-                        getFebOfThisYearInMillis(1, 1),
-                        false,
-                        DateUtils.FORMAT_24HOUR));
-
-        assertEquals(
-                "Feb 2, 12:00 – 1:00 AM",
-                Utils.getDurationString(
-                        RuntimeEnvironment.application,
-                        DATE_THIS_YEAR_2_1_MS,
-                        getFebOfThisYearInMillis(2, 0),
-                        getFebOfThisYearInMillis(2, 1),
-                        false,
-                        DateUtils.FORMAT_12HOUR));
-        assertEquals(
-                "Feb 2, 00:00 – 01:00",
-                Utils.getDurationString(
-                        RuntimeEnvironment.application,
-                        DATE_THIS_YEAR_2_1_MS,
-                        getFebOfThisYearInMillis(2, 0),
-                        getFebOfThisYearInMillis(2, 1),
-                        false,
-                        DateUtils.FORMAT_24HOUR));
-        assertEquals(
-                "2/2, 12:00 – 1:00 AM",
-                Utils.getDurationString(
-                        RuntimeEnvironment.application,
-                        DATE_THIS_YEAR_2_1_MS,
-                        getFebOfThisYearInMillis(2, 0),
-                        getFebOfThisYearInMillis(2, 1),
-                        true,
-                        DateUtils.FORMAT_12HOUR));
-        assertEquals(
-                "2/2, 00:00 – 01:00",
-                Utils.getDurationString(
-                        RuntimeEnvironment.application,
-                        DATE_THIS_YEAR_2_1_MS,
-                        getFebOfThisYearInMillis(2, 0),
-                        getFebOfThisYearInMillis(2, 1),
-                        true,
-                        DateUtils.FORMAT_24HOUR));
-    }
-
-    @Test
-    public void testEndOfDay() {
-        for (boolean useShortFormat : PARAM_USE_SHORT_FORMAT) {
-            assertEquals(
-                    "11:00 PM – 12:00 AM",
-                    Utils.getDurationString(
-                            RuntimeEnvironment.application,
-                            DATE_THIS_YEAR_2_1_MS,
-                            getFebOfThisYearInMillis(1, 23),
-                            getFebOfThisYearInMillis(2, 0),
-                            useShortFormat,
-                            DateUtils.FORMAT_12HOUR));
-            assertEquals(
-                    "23:00 – 00:00",
-                    Utils.getDurationString(
-                            RuntimeEnvironment.application,
-                            DATE_THIS_YEAR_2_1_MS,
-                            getFebOfThisYearInMillis(1, 23),
-                            getFebOfThisYearInMillis(2, 0),
-                            useShortFormat,
-                            DateUtils.FORMAT_24HOUR));
-        }
-
-        assertEquals(
-                "Feb 2, 11:00 PM – 12:00 AM",
-                Utils.getDurationString(
-                        RuntimeEnvironment.application,
-                        DATE_THIS_YEAR_2_1_MS,
-                        getFebOfThisYearInMillis(2, 23),
-                        getFebOfThisYearInMillis(3, 0),
-                        false,
-                        DateUtils.FORMAT_12HOUR));
-        assertEquals(
-                "Feb 2, 23:00 – 00:00",
-                Utils.getDurationString(
-                        RuntimeEnvironment.application,
-                        DATE_THIS_YEAR_2_1_MS,
-                        getFebOfThisYearInMillis(2, 23),
-                        getFebOfThisYearInMillis(3, 0),
-                        false,
-                        DateUtils.FORMAT_24HOUR));
-        assertEquals(
-                "2/2, 11:00 PM – 12:00 AM",
-                Utils.getDurationString(
-                        RuntimeEnvironment.application,
-                        DATE_THIS_YEAR_2_1_MS,
-                        getFebOfThisYearInMillis(2, 23),
-                        getFebOfThisYearInMillis(3, 0),
-                        true,
-                        DateUtils.FORMAT_12HOUR));
-        assertEquals(
-                "2/2, 23:00 – 00:00",
-                Utils.getDurationString(
-                        RuntimeEnvironment.application,
-                        DATE_THIS_YEAR_2_1_MS,
-                        getFebOfThisYearInMillis(2, 23),
-                        getFebOfThisYearInMillis(3, 0),
-                        true,
-                        DateUtils.FORMAT_24HOUR));
-        assertEquals(
-                "2/2, 12:00 AM – 2/3, 12:00 AM",
-                Utils.getDurationString(
-                        RuntimeEnvironment.application,
-                        DATE_THIS_YEAR_2_1_MS,
-                        getFebOfThisYearInMillis(2, 0),
-                        getFebOfThisYearInMillis(3, 0),
-                        true,
-                        DateUtils.FORMAT_12HOUR));
-        assertEquals(
-                "2/2, 00:00 – 2/3, 00:00",
-                Utils.getDurationString(
-                        RuntimeEnvironment.application,
-                        DATE_THIS_YEAR_2_1_MS,
-                        getFebOfThisYearInMillis(2, 0),
-                        getFebOfThisYearInMillis(3, 0),
-                        true,
-                        DateUtils.FORMAT_24HOUR));
-    }
-
-    @Test
-    public void testMidnight() {
-        for (boolean useShortFormat : PARAM_USE_SHORT_FORMAT) {
-            assertEquals(
-                    "12:00 AM",
-                    Utils.getDurationString(
-                            RuntimeEnvironment.application,
-                            DATE_THIS_YEAR_2_1_MS,
-                            DATE_THIS_YEAR_2_1_MS,
-                            DATE_THIS_YEAR_2_1_MS,
-                            useShortFormat,
-                            DateUtils.FORMAT_12HOUR));
-            assertEquals(
-                    "00:00",
-                    Utils.getDurationString(
-                            RuntimeEnvironment.application,
-                            DATE_THIS_YEAR_2_1_MS,
-                            DATE_THIS_YEAR_2_1_MS,
-                            DATE_THIS_YEAR_2_1_MS,
-                            useShortFormat,
-                            DateUtils.FORMAT_24HOUR));
-        }
-    }
-
-    @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();
-
-        TimeZone.setDefault(TimeZone.getTimeZone("Asia/Seoul"));
-
-        // 2015.01.01 00:00 in KST = 2014.12.31 15:00 in UTC
-        long date2015StartMs = new GregorianCalendar(2015, Calendar.JANUARY, 1).getTimeInMillis();
-
-        // 2015.01.01 10:00 in KST = 2015.01.01 01:00 in UTC
-        long date2015Start10AMMs =
-                new GregorianCalendar(2015, Calendar.JANUARY, 1, 10, 0).getTimeInMillis();
-
-        // Those two times aren't in the same day in UTC, but they are in KST.
-        assertTrue(Utils.isInGivenDay(date2015StartMs, date2015Start10AMMs));
-
-        TimeZone.setDefault(timeZone);
-    }
-
-    @Test
-    public void testIsInternalTvInputInvalidInternalInputId() {
-        String inputId = "tv.comp";
-        assertFalse(Utils.isInternalTvInput(RuntimeEnvironment.application, inputId));
-    }
-}
diff --git a/tests/unit/Android.mk b/tests/unit/Android.mk
index 80dbfee..5ea7ccd 100644
--- a/tests/unit/Android.mk
+++ b/tests/unit/Android.mk
@@ -9,7 +9,7 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     androidx.test.runner \
-    mockito-robolectric-prebuilt \
+    mockito-target \
     tv-test-common \
 
 LOCAL_JAVA_LIBRARIES := \
diff --git a/tests/unit/AndroidManifest.xml b/tests/unit/AndroidManifest.xml
index 5ee17de..c7d2f52 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="28" android:minSdkVersion="23" />
+    <uses-sdk android:targetSdkVersion="27" android:minSdkVersion="23" />
 
     <instrumentation
         android:name="androidx.test.runner.AndroidJUnitRunner"
diff --git a/tests/unit/src/com/android/tv/CurrentPositionMediatorTest.java b/tests/unit/src/com/android/tv/CurrentPositionMediatorTest.java
index 052123c..4b85eaa 100644
--- a/tests/unit/src/com/android/tv/CurrentPositionMediatorTest.java
+++ b/tests/unit/src/com/android/tv/CurrentPositionMediatorTest.java
@@ -53,9 +53,9 @@
     public void testOnSeekRequested() {
         long seekToTimeMs = System.currentTimeMillis() - REQUEST_TIMEOUT_MS * 3;
         mMediator.onSeekRequested(seekToTimeMs);
-    assertWithMessage("Seek request time")
-        .that(mMediator.mSeekRequestTimeMs)
-        .isNotSameInstanceAs(INVALID_TIME);
+        assertWithMessage("Seek request time")
+                .that(mMediator.mSeekRequestTimeMs)
+                .isNotSameAs(INVALID_TIME);
         assertWithMessage("Current position")
                 .that(mMediator.mCurrentPositionMs)
                 .isEqualTo(seekToTimeMs);
@@ -68,15 +68,15 @@
         long newCurrentTimeMs = seekToTimeMs + REQUEST_TIMEOUT_MS;
         mMediator.onSeekRequested(seekToTimeMs);
         mMediator.onCurrentPositionChanged(newCurrentTimeMs);
-    assertWithMessage("Seek request time")
-        .that(mMediator.mSeekRequestTimeMs)
-        .isNotSameInstanceAs(INVALID_TIME);
-    assertWithMessage("Current position")
-        .that(mMediator.mCurrentPositionMs)
-        .isNotSameInstanceAs(seekToTimeMs);
-    assertWithMessage("Current position")
-        .that(mMediator.mCurrentPositionMs)
-        .isNotSameInstanceAs(newCurrentTimeMs);
+        assertWithMessage("Seek request time")
+                .that(mMediator.mSeekRequestTimeMs)
+                .isNotSameAs(INVALID_TIME);
+        assertWithMessage("Current position")
+                .that(mMediator.mCurrentPositionMs)
+                .isNotSameAs(seekToTimeMs);
+        assertWithMessage("Current position")
+                .that(mMediator.mCurrentPositionMs)
+                .isNotSameAs(newCurrentTimeMs);
     }
 
     @UiThreadTest
diff --git a/tests/unit/src/com/android/tv/data/ChannelDataManagerTest.java b/tests/unit/src/com/android/tv/data/ChannelDataManagerTest.java
index ecae18a..71ccaf3 100644
--- a/tests/unit/src/com/android/tv/data/ChannelDataManagerTest.java
+++ b/tests/unit/src/com/android/tv/data/ChannelDataManagerTest.java
@@ -56,7 +56,7 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.ArgumentMatchers;
+import org.mockito.Matchers;
 import org.mockito.Mockito;
 
 /**
@@ -92,29 +92,35 @@
         mContentResolver = new FakeContentResolver();
         mContentResolver.addProvider(TvContract.AUTHORITY, mContentProvider);
         mListener = new TestChannelDataManagerListener();
-    getInstrumentation()
-        .runOnMainSync(
-            new Runnable() {
-              @Override
-              public void run() {
-                TvInputManagerHelper mockHelper = Mockito.mock(TvInputManagerHelper.class);
-                Mockito.when(mockHelper.hasTvInputInfo(ArgumentMatchers.anyString()))
-                    .thenReturn(true);
-                Context mockContext = Mockito.mock(Context.class);
-                Mockito.when(mockContext.getContentResolver()).thenReturn(mContentResolver);
-                Mockito.when(mockContext.checkSelfPermission(ArgumentMatchers.anyString()))
-                    .thenAnswer(
-                        invocation -> {
-                          Object[] args = invocation.getArguments();
-                          return getTargetContext().checkSelfPermission(((String) args[0]));
-                        });
+        getInstrumentation()
+                .runOnMainSync(
+                        new Runnable() {
+                            @Override
+                            public void run() {
+                                TvInputManagerHelper mockHelper =
+                                        Mockito.mock(TvInputManagerHelper.class);
+                                Mockito.when(mockHelper.hasTvInputInfo(Matchers.anyString()))
+                                        .thenReturn(true);
+                                Context mockContext = Mockito.mock(Context.class);
+                                Mockito.when(mockContext.getContentResolver())
+                                        .thenReturn(mContentResolver);
+                                Mockito.when(mockContext.checkSelfPermission(Matchers.anyString()))
+                                  .thenAnswer(
+                                          invocation -> {
+                                              Object[] args = invocation.getArguments();
+                                              return getTargetContext()
+                                                      .checkSelfPermission(((String) args[0]));
+                                          });
 
-                mChannelDataManager =
-                    new ChannelDataManager(
-                        mockContext, mockHelper, AsyncTask.SERIAL_EXECUTOR, mContentResolver);
-                mChannelDataManager.addListener(mListener);
-              }
-            });
+                                mChannelDataManager =
+                                        new ChannelDataManager(
+                                                mockContext,
+                                                mockHelper,
+                                                AsyncTask.SERIAL_EXECUTOR,
+                                                mContentResolver);
+                                mChannelDataManager.addListener(mListener);
+                            }
+                        });
     }
 
     @After
diff --git a/tests/unit/src/com/android/tv/data/ChannelImplTest.java b/tests/unit/src/com/android/tv/data/ChannelImplTest.java
index df2f1a1..86cfab6 100644
--- a/tests/unit/src/com/android/tv/data/ChannelImplTest.java
+++ b/tests/unit/src/com/android/tv/data/ChannelImplTest.java
@@ -25,24 +25,20 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
-
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
-
 import com.android.tv.data.api.Channel;
 import com.android.tv.testing.ComparatorTester;
 import com.android.tv.util.TvInputManagerHelper;
-
+import java.util.Comparator;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.ArgumentMatchers;
+import org.mockito.Matchers;
 import org.mockito.Mockito;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 
-import java.util.Comparator;
-
 /** Tests for {@link ChannelImpl}. */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
@@ -50,7 +46,7 @@
     // 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 = "com.android.tv.invalid_tv_input";
-    // Used for testing TV inputs defined inside of TV app.
+    // Used for testing TV inputs defined inside of Live TV.
     private static final String LIVE_CHANNELS_PACKAGE_NAME = "com.android.tv";
     // Used for testing a TV input which doesn't have its leanback launcher activity.
     private static final String NONE_LEANBACK_TV_INPUT_PACKAGE_NAME =
@@ -119,7 +115,7 @@
                             }
                         })
                 .when(mockPackageManager)
-                .getActivityInfo(ArgumentMatchers.<ComponentName>any(), ArgumentMatchers.anyInt());
+                .getActivityInfo(Mockito.<ComponentName>any(), Mockito.anyInt());
 
         mMockContext = Mockito.mock(Context.class);
         Mockito.when(mMockContext.getApplicationContext()).thenReturn(mMockContext);
@@ -257,7 +253,7 @@
     @Test
     public void testComparator() {
         TvInputManagerHelper manager = Mockito.mock(TvInputManagerHelper.class);
-        Mockito.when(manager.isPartnerInput(ArgumentMatchers.anyString()))
+        Mockito.when(manager.isPartnerInput(Matchers.anyString()))
                 .thenAnswer(
                         new Answer<Boolean>() {
                             @Override
@@ -267,18 +263,17 @@
                             }
                         });
         Comparator<Channel> comparator = new TestChannelComparator(manager);
-        ComparatorTester comparatorTester =
-                new ComparatorTester(comparator).permitInconsistencyWithEquals();
-        comparatorTester.addEqualityGroup(
+        ComparatorTester<Channel> comparatorTester = ComparatorTester.withoutEqualsTest(comparator);
+        comparatorTester.addComparableGroup(
                 new ChannelImpl.Builder().setInputId(PARTNER_INPUT_ID).build());
-        comparatorTester.addEqualityGroup(new ChannelImpl.Builder().setInputId("1").build());
-        comparatorTester.addEqualityGroup(
+        comparatorTester.addComparableGroup(new ChannelImpl.Builder().setInputId("1").build());
+        comparatorTester.addComparableGroup(
                 new ChannelImpl.Builder().setInputId("1").setDisplayNumber("2").build());
-        comparatorTester.addEqualityGroup(
+        comparatorTester.addComparableGroup(
                 new ChannelImpl.Builder().setInputId("2").setDisplayNumber("1.0").build());
 
         // display name does not affect comparator
-        comparatorTester.addEqualityGroup(
+        comparatorTester.addComparableGroup(
                 new ChannelImpl.Builder()
                         .setInputId("2")
                         .setDisplayNumber("1.62")
@@ -294,12 +289,12 @@
                         .setDisplayNumber("1.62")
                         .setDisplayName("test3")
                         .build());
-        comparatorTester.addEqualityGroup(
+        comparatorTester.addComparableGroup(
                 new ChannelImpl.Builder().setInputId("2").setDisplayNumber("2.0").build());
         // Numeric display number sorting
-        comparatorTester.addEqualityGroup(
+        comparatorTester.addComparableGroup(
                 new ChannelImpl.Builder().setInputId("2").setDisplayNumber("12.2").build());
-        comparatorTester.testCompare();
+        comparatorTester.test();
     }
 
     /**
@@ -311,7 +306,7 @@
     @Test
     public void testComparatorLabel() {
         TvInputManagerHelper manager = Mockito.mock(TvInputManagerHelper.class);
-        Mockito.when(manager.isPartnerInput(ArgumentMatchers.anyString()))
+        Mockito.when(manager.isPartnerInput(Matchers.anyString()))
                 .thenAnswer(
                         new Answer<Boolean>() {
                             @Override
@@ -321,21 +316,20 @@
                             }
                         });
         Comparator<Channel> comparator = new ChannelComparatorWithDescriptionAsLabel(manager);
-        ComparatorTester comparatorTester =
-                new ComparatorTester(comparator).permitInconsistencyWithEquals();
+        ComparatorTester<Channel> comparatorTester = ComparatorTester.withoutEqualsTest(comparator);
 
-        comparatorTester.addEqualityGroup(
+        comparatorTester.addComparableGroup(
                 new ChannelImpl.Builder().setInputId(PARTNER_INPUT_ID).setDescription("A").build());
 
         // The description is used as a label for this test.
-        comparatorTester.addEqualityGroup(
+        comparatorTester.addComparableGroup(
                 new ChannelImpl.Builder().setDescription("A").setInputId("1").build());
-        comparatorTester.addEqualityGroup(
+        comparatorTester.addComparableGroup(
                 new ChannelImpl.Builder().setDescription("A").setInputId("2").build());
-        comparatorTester.addEqualityGroup(
+        comparatorTester.addComparableGroup(
                 new ChannelImpl.Builder().setDescription("B").setInputId("1").build());
 
-        comparatorTester.testCompare();
+        comparatorTester.test();
     }
 
     @Test
diff --git a/tests/unit/src/com/android/tv/features/FeaturesTest.java b/tests/unit/src/com/android/tv/features/FeaturesTest.java
new file mode 100644
index 0000000..e35758c
--- /dev/null
+++ b/tests/unit/src/com/android/tv/features/FeaturesTest.java
@@ -0,0 +1,36 @@
+/*
+ * 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.features;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/** Test for features. */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+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.
+        assertThat(TvFeatures.TEST_FEATURE.isEnabled(null)).isFalse();
+    }
+}
diff --git a/tests/unit/src/com/android/tv/menu/MenuTest.java b/tests/unit/src/com/android/tv/menu/MenuTest.java
index 7058316..e384c39 100644
--- a/tests/unit/src/com/android/tv/menu/MenuTest.java
+++ b/tests/unit/src/com/android/tv/menu/MenuTest.java
@@ -25,7 +25,6 @@
 import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.ArgumentMatchers;
 import org.mockito.Matchers;
 import org.mockito.Mockito;
 import org.mockito.invocation.InvocationOnMock;
@@ -43,10 +42,8 @@
     public void setUp() {
         mMenuView = Mockito.mock(IMenuView.class);
         MenuRowFactory factory = Mockito.mock(MenuRowFactory.class);
-    Mockito.when(
-            factory.createMenuRow(
-                ArgumentMatchers.any(Menu.class), ArgumentMatchers.any(Class.class)))
-        .thenReturn(null);
+        Mockito.when(factory.createMenuRow(Mockito.any(Menu.class), Mockito.any(Class.class)))
+                .thenReturn(null);
         mVisibilityChangeListener = Mockito.mock(OnMenuVisibilityChangeListener.class);
         mMenu = new Menu(getTargetContext(), mMenuView, factory, mVisibilityChangeListener);
         mMenu.disableAnimationForTest();
diff --git a/tests/unit/src/com/android/tv/menu/TvOptionsRowAdapterTest.java b/tests/unit/src/com/android/tv/menu/TvOptionsRowAdapterTest.java
index 64a055a..5ecbdf0 100644
--- a/tests/unit/src/com/android/tv/menu/TvOptionsRowAdapterTest.java
+++ b/tests/unit/src/com/android/tv/menu/TvOptionsRowAdapterTest.java
@@ -24,7 +24,6 @@
 import android.text.TextUtils;
 import androidx.test.filters.MediumTest;
 import androidx.test.runner.AndroidJUnit4;
-import com.android.tv.common.flags.impl.DefaultLegacyFlags;
 import com.android.tv.testing.activities.BaseMainActivityTestCase;
 import com.android.tv.testing.constants.Constants;
 import com.android.tv.testing.testinput.ChannelState;
@@ -50,9 +49,7 @@
     @Before
     public void setUp() {
         super.setUp();
-        mTvOptionsRowAdapter =
-                new TvOptionsRowAdapter(
-                        mActivity, Collections.emptyList(), DefaultLegacyFlags.DEFAULT);
+        mTvOptionsRowAdapter = new TvOptionsRowAdapter(mActivity, Collections.emptyList());
         tuneToChannel(TvTestInputConstants.CH_1_DEFAULT_DONT_MODIFY);
         waitUntilAudioTracksHaveSize(1);
         waitUntilAudioTrackSelected(ChannelState.DEFAULT.getSelectedAudioTrackId());
@@ -76,10 +73,10 @@
         waitUntilAudioTrackSelected(Constants.EN_STEREO_AUDIO_TRACK.getId());
 
         boolean result = mTvOptionsRowAdapter.updateMultiAudioAction();
-        assertWithMessage("update Action had change").that(result).isTrue();
-        assertWithMessage("Multi Audio enabled")
-                .that(MenuAction.SELECT_AUDIO_LANGUAGE_ACTION.isEnabled())
-                .isTrue();
+    assertWithMessage("update Action had change").that(result).isTrue();
+    assertWithMessage("Multi Audio enabled")
+        .that(MenuAction.SELECT_AUDIO_LANGUAGE_ACTION.isEnabled())
+        .isTrue();
     }
 
     @Test
@@ -94,10 +91,10 @@
         waitUntilAudioTrackSelected(Constants.GENERIC_AUDIO_TRACK.getId());
 
         boolean result = mTvOptionsRowAdapter.updateMultiAudioAction();
-        assertWithMessage("update Action had change").that(result).isTrue();
-        assertWithMessage("Multi Audio enabled")
-                .that(MenuAction.SELECT_AUDIO_LANGUAGE_ACTION.isEnabled())
-                .isFalse();
+    assertWithMessage("update Action had change").that(result).isTrue();
+    assertWithMessage("Multi Audio enabled")
+        .that(MenuAction.SELECT_AUDIO_LANGUAGE_ACTION.isEnabled())
+        .isFalse();
     }
 
     @Test
@@ -113,10 +110,10 @@
         waitUntilVideoTrackSelected(data.mSelectedVideoTrackId);
 
         boolean result = mTvOptionsRowAdapter.updateMultiAudioAction();
-        assertWithMessage("update Action had change").that(result).isTrue();
-        assertWithMessage("Multi Audio enabled")
-                .that(MenuAction.SELECT_AUDIO_LANGUAGE_ACTION.isEnabled())
-                .isFalse();
+    assertWithMessage("update Action had change").that(result).isTrue();
+    assertWithMessage("Multi Audio enabled")
+        .that(MenuAction.SELECT_AUDIO_LANGUAGE_ACTION.isEnabled())
+        .isFalse();
     }
 
     private void waitUntilAudioTracksHaveSize(int expected) {
diff --git a/tests/unit/src/com/android/tv/recommendation/RecommendationUtils.java b/tests/unit/src/com/android/tv/recommendation/RecommendationUtils.java
index eb012f4..b929a0a 100644
--- a/tests/unit/src/com/android/tv/recommendation/RecommendationUtils.java
+++ b/tests/unit/src/com/android/tv/recommendation/RecommendationUtils.java
@@ -26,7 +26,7 @@
 import java.util.Random;
 import java.util.TreeMap;
 import java.util.concurrent.TimeUnit;
-import org.mockito.ArgumentMatchers;
+import org.mockito.Matchers;
 import org.mockito.Mockito;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
@@ -57,16 +57,17 @@
                         })
                 .when(dataManager)
                 .getChannelRecords();
-    Mockito.doAnswer(
-            new Answer<ChannelRecord>() {
-              @Override
-              public ChannelRecord answer(InvocationOnMock invocation) throws Throwable {
-                long channelId = (long) invocation.getArguments()[0];
-                return channelRecordSortedMap.get(channelId);
-              }
-            })
-        .when(dataManager)
-        .getChannelRecord(ArgumentMatchers.anyLong());
+        Mockito.doAnswer(
+                        new Answer<ChannelRecord>() {
+                            @Override
+                            public ChannelRecord answer(InvocationOnMock invocation)
+                                    throws Throwable {
+                                long channelId = (long) invocation.getArguments()[0];
+                                return channelRecordSortedMap.get(channelId);
+                            }
+                        })
+                .when(dataManager)
+                .getChannelRecord(Matchers.anyLong());
         return dataManager;
     }
 
@@ -130,7 +131,7 @@
                     // Time hopping with random minutes.
                     latestWatchEndTimeMs += TimeUnit.MINUTES.toMillis(mRandom.nextInt(30) + 1);
                 }
-        long watchedDurationMs = mRandom.nextInt((int) maxWatchDurationMs) + 1L;
+                long watchedDurationMs = mRandom.nextInt((int) maxWatchDurationMs) + 1;
                 if (!addWatchLog(channelId, latestWatchEndTimeMs, watchedDurationMs)) {
                     return false;
                 }
diff --git a/tests/unit/src/com/android/tv/recommendation/RoutineWatchEvaluatorTest.java b/tests/unit/src/com/android/tv/recommendation/RoutineWatchEvaluatorTest.java
index 6cb0e08..d914905 100644
--- a/tests/unit/src/com/android/tv/recommendation/RoutineWatchEvaluatorTest.java
+++ b/tests/unit/src/com/android/tv/recommendation/RoutineWatchEvaluatorTest.java
@@ -17,22 +17,17 @@
 package com.android.tv.recommendation;
 
 import static com.google.common.truth.Truth.assertThat;
-
 import static org.junit.Assert.assertEquals;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
-
-import com.android.tv.data.ProgramImpl;
-import com.android.tv.data.api.Program;
+import com.android.tv.data.Program;
 import com.android.tv.recommendation.RoutineWatchEvaluator.ProgramTime;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
 import java.util.Calendar;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 /** Tests for {@link RoutineWatchEvaluator}. */
 @SmallTest
@@ -126,15 +121,15 @@
     @Test
     public void testCalculateTitleMatchScore_longerMatchIsBetter() {
         String base = "foo bar baz";
-    assertThat(
-            new ScoredItem[] {
-              score(base, ""),
-              score(base, "bar"),
-              score(base, "foo bar"),
-              score(base, "foo bar baz")
-            })
-        .asList()
-        .isInOrder();
+        assertThat(
+                        new ScoredItem[] {
+                            score(base, ""),
+                            score(base, "bar"),
+                            score(base, "foo bar"),
+                            score(base, "foo bar baz")
+                        })
+                .asList()
+                .isOrdered();
     }
 
     @Test
@@ -325,7 +320,7 @@
     private Program createDummyProgram(Calendar startTime, long programDurationMs) {
         long startTimeMs = startTime.getTimeInMillis();
 
-        return new ProgramImpl.Builder()
+        return new Program.Builder()
                 .setStartTimeUtcMillis(startTimeMs)
                 .setEndTimeUtcMillis(startTimeMs + programDurationMs)
                 .build();
diff --git a/tests/unit/src/com/android/tv/util/MockTvSingletons.java b/tests/unit/src/com/android/tv/util/MockTvSingletons.java
index d9ff5e7..fd4b43c 100644
--- a/tests/unit/src/com/android/tv/util/MockTvSingletons.java
+++ b/tests/unit/src/com/android/tv/util/MockTvSingletons.java
@@ -17,15 +17,16 @@
 package com.android.tv.util;
 
 import android.content.Context;
-
 import com.android.tv.InputSessionManager;
 import com.android.tv.MainActivityWrapper;
 import com.android.tv.TvApplication;
 import com.android.tv.TvSingletons;
 import com.android.tv.analytics.Analytics;
 import com.android.tv.analytics.Tracker;
+import com.android.tv.common.experiments.ExperimentLoader;
 import com.android.tv.common.flags.impl.DefaultBackendKnobsFlags;
 import com.android.tv.common.flags.impl.DefaultCloudEpgFlags;
+import com.android.tv.common.flags.impl.DefaultConcurrentDvrPlaybackFlags;
 import com.android.tv.common.flags.impl.DefaultUiFlags;
 import com.android.tv.common.recording.RecordingStorageStatusManager;
 import com.android.tv.common.singletons.HasSingletons;
@@ -33,6 +34,7 @@
 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.data.epg.EpgReader;
 import com.android.tv.dvr.DvrDataManager;
 import com.android.tv.dvr.DvrManager;
@@ -40,14 +42,11 @@
 import com.android.tv.dvr.DvrWatchedPositionManager;
 import com.android.tv.dvr.recorder.RecordingScheduler;
 import com.android.tv.perf.PerformanceMonitor;
-import com.android.tv.testing.fakes.FakeClock;
+import com.android.tv.testing.FakeClock;
 import com.android.tv.tunerinputcontroller.BuiltInTunerManager;
-
 import com.google.common.base.Optional;
-
-import dagger.Lazy;
-
 import java.util.concurrent.Executor;
+import javax.inject.Provider;
 
 /** Mock {@link TvSingletons} class. */
 public class MockTvSingletons implements TvSingletons, HasSingletons<TvSingletons> {
@@ -57,6 +56,8 @@
     private final DefaultBackendKnobsFlags mBackendFlags = new DefaultBackendKnobsFlags();
     private final DefaultCloudEpgFlags mCloudEpgFlags = new DefaultCloudEpgFlags();
     private final DefaultUiFlags mUiFlags = new DefaultUiFlags();
+    private final DefaultConcurrentDvrPlaybackFlags mConcurrentDvrPlaybackFlags =
+            new DefaultConcurrentDvrPlaybackFlags();
     private PerformanceMonitor mPerformanceMonitor;
 
     public MockTvSingletons(Context context) {
@@ -77,11 +78,21 @@
     }
 
     @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();
     }
@@ -137,11 +148,16 @@
     }
 
     @Override
-    public Lazy<EpgReader> providesEpgReader() {
+    public Provider<EpgReader> providesEpgReader() {
         return mApp.providesEpgReader();
     }
 
     @Override
+    public EpgFetcher getEpgFetcher() {
+        return mApp.getEpgFetcher();
+    }
+
+    @Override
     public SetupUtils getSetupUtils() {
         return mApp.getSetupUtils();
     }
@@ -152,11 +168,21 @@
     }
 
     @Override
+    public ExperimentLoader getExperimentLoader() {
+        return mApp.getExperimentLoader();
+    }
+
+    @Override
     public MainActivityWrapper getMainActivityWrapper() {
         return mApp.getMainActivityWrapper();
     }
 
     @Override
+    public com.android.tv.util.account.AccountHelper getAccountHelper() {
+        return mApp.getAccountHelper();
+    }
+
+    @Override
     public boolean isRunningInMainProcess() {
         return mApp.isRunningInMainProcess();
     }
@@ -196,6 +222,11 @@
     }
 
     @Override
+    public DefaultConcurrentDvrPlaybackFlags getConcurrentDvrPlaybackFlags() {
+        return mConcurrentDvrPlaybackFlags;
+    }
+
+    @Override
     public TvSingletons singletons() {
         return this;
     }
diff --git a/tests/unit/src/com/android/tv/util/TvInputManagerHelperTest.java b/tests/unit/src/com/android/tv/util/TvInputManagerHelperTest.java
index ab3c5e7..7e35d76 100644
--- a/tests/unit/src/com/android/tv/util/TvInputManagerHelperTest.java
+++ b/tests/unit/src/com/android/tv/util/TvInputManagerHelperTest.java
@@ -20,23 +20,18 @@
 
 import android.content.pm.ResolveInfo;
 import android.media.tv.TvInputInfo;
-
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
-
 import com.android.tv.testing.ComparatorTester;
 import com.android.tv.testing.utils.TestUtils;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentMatchers;
-import org.mockito.Mockito;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
 
 /** Test for {@link TvInputManagerHelper} */
 @SmallTest
@@ -92,13 +87,13 @@
 
         TvInputManagerHelper manager = createMockTvInputManager();
 
-        ComparatorTester comparatorTester =
-                new ComparatorTester(new TvInputManagerHelper.InputComparatorInternal(manager))
-                        .permitInconsistencyWithEquals();
+        ComparatorTester<TvInputInfo> comparatorTester =
+                ComparatorTester.withoutEqualsTest(
+                        new TvInputManagerHelper.InputComparatorInternal(manager));
         for (TvInputInfo input : inputs) {
-            comparatorTester.addEqualityGroup(input);
+            comparatorTester.addComparableGroup(input);
         }
-        comparatorTester.testCompare();
+        comparatorTester.test();
     }
 
     @Test
@@ -148,17 +143,15 @@
 
         TvInputManagerHelper manager = createMockTvInputManager();
 
-        ComparatorTester comparatorTester =
-                new ComparatorTester(
-                                new TvInputManagerHelper.HardwareInputComparator(
-                                        getContext(), manager))
-                        .permitInconsistencyWithEquals();
+        ComparatorTester<TvInputInfo> comparatorTester =
+                ComparatorTester.withoutEqualsTest(
+                        new TvInputManagerHelper.HardwareInputComparator(getContext(), manager));
         comparatorTester
-                .addEqualityGroup(hdmi3)
-                .addEqualityGroup(hdmi2)
-                .addEqualityGroup(hdmi1)
-                .addEqualityGroup(hdmi4)
-                .testCompare();
+                .addComparableGroup(hdmi3)
+                .addComparableGroup(hdmi2)
+                .addComparableGroup(hdmi1)
+                .addComparableGroup(hdmi4)
+                .test();
     }
 
     @Test
@@ -209,12 +202,10 @@
 
         TvInputManagerHelper manager = createMockTvInputManager();
 
-        ComparatorTester comparatorTester =
-                new ComparatorTester(
-                                new TvInputManagerHelper.HardwareInputComparator(
-                                        getContext(), manager))
-                        .permitInconsistencyWithEquals();
-        comparatorTester.addEqualityGroup(cec1).addEqualityGroup(cec2).testCompare();
+        ComparatorTester<TvInputInfo> comparatorTester =
+                ComparatorTester.withoutEqualsTest(
+                        new TvInputManagerHelper.HardwareInputComparator(getContext(), manager));
+        comparatorTester.addComparableGroup(cec1).addComparableGroup(cec2).test();
     }
 
     private TvInputManagerHelper createMockTvInputManager() {
@@ -228,7 +219,7 @@
                             }
                         })
                 .when(manager)
-                .isPartnerInput(ArgumentMatchers.<TvInputInfo>any());
+                .isPartnerInput(Mockito.<TvInputInfo>any());
         Mockito.doAnswer(
                         new Answer<String>() {
                             @Override
@@ -238,7 +229,7 @@
                             }
                         })
                 .when(manager)
-                .loadLabel(ArgumentMatchers.<TvInputInfo>any());
+                .loadLabel(Mockito.<TvInputInfo>any());
         Mockito.doAnswer(
                         new Answer<String>() {
                             @Override
@@ -248,7 +239,7 @@
                             }
                         })
                 .when(manager)
-                .loadCustomLabel(ArgumentMatchers.<TvInputInfo>any());
+                .loadCustomLabel(Mockito.<TvInputInfo>any());
         Mockito.doAnswer(
                         new Answer<TvInputInfo>() {
                             @Override
@@ -260,7 +251,7 @@
                             }
                         })
                 .when(manager)
-                .getTvInputInfo(ArgumentMatchers.<String>any());
+                .getTvInputInfo(Mockito.<String>any());
         return manager;
     }
 
diff --git a/tests/unit/src/com/android/tv/util/images/ImageCacheTest.java b/tests/unit/src/com/android/tv/util/images/ImageCacheTest.java
index 6e96824..4172213 100644
--- a/tests/unit/src/com/android/tv/util/images/ImageCacheTest.java
+++ b/tests/unit/src/com/android/tv/util/images/ImageCacheTest.java
@@ -52,28 +52,28 @@
     public void testPutIfLarger_smaller() throws Exception {
 
         mImageCache.putIfNeeded(INFO_50);
-    assertWithMessage("before").that(mImageCache.get(KEY)).isSameInstanceAs(INFO_50);
+    assertWithMessage("before").that(mImageCache.get(KEY)).isSameAs(INFO_50);
 
         mImageCache.putIfNeeded(INFO_25);
-    assertWithMessage("after").that(mImageCache.get(KEY)).isSameInstanceAs(INFO_50);
+    assertWithMessage("after").that(mImageCache.get(KEY)).isSameAs(INFO_50);
     }
 
     @Test
     public void testPutIfLarger_larger() throws Exception {
         mImageCache.putIfNeeded(INFO_50);
-    assertWithMessage("before").that(mImageCache.get(KEY)).isSameInstanceAs(INFO_50);
+    assertWithMessage("before").that(mImageCache.get(KEY)).isSameAs(INFO_50);
 
         mImageCache.putIfNeeded(INFO_100);
-    assertWithMessage("after").that(mImageCache.get(KEY)).isSameInstanceAs(INFO_100);
+    assertWithMessage("after").that(mImageCache.get(KEY)).isSameAs(INFO_100);
     }
 
     @Test
     public void testPutIfLarger_alreadyMax() throws Exception {
 
         mImageCache.putIfNeeded(INFO_100);
-    assertWithMessage("before").that(mImageCache.get(KEY)).isSameInstanceAs(INFO_100);
+    assertWithMessage("before").that(mImageCache.get(KEY)).isSameAs(INFO_100);
 
         mImageCache.putIfNeeded(INFO_200);
-    assertWithMessage("after").that(mImageCache.get(KEY)).isSameInstanceAs(INFO_100);
+    assertWithMessage("after").that(mImageCache.get(KEY)).isSameAs(INFO_100);
     }
 }
diff --git a/tuner/Android.bp b/tuner/Android.bp
index d1df99f..215a1e5 100644
--- a/tuner/Android.bp
+++ b/tuner/Android.bp
@@ -20,25 +20,25 @@
     sdk_version: "system_current",
     resource_dirs: ["res"],
     libs: [
+        "tv-auto-value-jar",
+        "tv-auto-factory-jar",
         "android-support-annotations",
+        "tv-error-prone-annotations-jar",
+        "tv-guava-android-jar",
+        "tv-javax-annotations-jar",
+        "jsr330",
+        "tv-lib-dagger",
+        "tv-lib-exoplayer",
+        "tv-lib-exoplayer-v2-core",
+        "live-tv-tuner-proto",
         "android-support-compat",
         "android-support-core-ui",
         "android-support-v7-palette",
         "android-support-v7-recyclerview",
-        "androidx.leanback_leanback",
+        "android-support-v17-leanback",
         "androidx.tvprovider_tvprovider",
-        "jsr330",
-        "live-tv-tuner-proto",
-        "tv-auto-value-jar",
-        "tv-auto-factory-jar",
-        "tv-common",
-        "tv-error-prone-annotations-jar",
-        "tv-guava-android-jar",
-        "tv-javax-annotations-jar",
-        "tv-lib-dagger",
-        "tv-lib-exoplayer",
-        "tv-lib-exoplayer-v2-core",
         "tv-lib-dagger-android",
+        "tv-common",
     ],
     plugins: [
         "tv-auto-value",
diff --git a/tuner/AndroidManifest.xml b/tuner/AndroidManifest.xml
index c084f3f..fd21771 100644
--- a/tuner/AndroidManifest.xml
+++ b/tuner/AndroidManifest.xml
@@ -18,7 +18,7 @@
     xmlns:tools="http://schemas.android.com/tools"
     package="com.android.tv.tuner"
     android:versionCode="1">
-  <uses-sdk android:targetSdkVersion="28" android:minSdkVersion="23"/>
+  <uses-sdk android:targetSdkVersion="27" android:minSdkVersion="23"/>
   <application tools:replace="android:appComponentFactory"
       android:appComponentFactory="android.support.v4.app.CoreComponentFactory" />
 </manifest>
diff --git a/tuner/SampleDvbTuner/AndroidManifest.xml b/tuner/SampleDvbTuner/AndroidManifest.xml
index da23f84..5ad927e 100755
--- a/tuner/SampleDvbTuner/AndroidManifest.xml
+++ b/tuner/SampleDvbTuner/AndroidManifest.xml
@@ -19,7 +19,7 @@
 
     <uses-sdk
         android:minSdkVersion="23"
-        android:targetSdkVersion="28" />
+        android:targetSdkVersion="27" />
 
     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
@@ -29,8 +29,6 @@
     <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
     <uses-permission android:name="com.android.providers.tv.permission.READ_EPG_DATA" />
     <uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA" />
-    <!-- Permission to modify Recorded Program -->
-    <uses-permission android:name="com.android.providers.tv.permission.ACCESS_ALL_EPG_DATA" />
 
     <!-- Permissions/feature for USB tuner -->
     <uses-permission android:name="android.permission.DVB_DEVICE" />
diff --git a/tuner/SampleDvbTuner/build.gradle b/tuner/SampleDvbTuner/build.gradle
index 28ad3e4..657a425 100644
--- a/tuner/SampleDvbTuner/build.gradle
+++ b/tuner/SampleDvbTuner/build.gradle
@@ -19,35 +19,48 @@
  * Experimental gradle configuration.  This file may not be up to date.
  */
 
+buildscript {
+    repositories {
+        mavenCentral()
+        google()
+        jcenter()
+    }
+    dependencies {
+        classpath 'com.android.tools.build:gradle:3.1.4'
+        classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.5'
+    }
+}
 apply plugin: 'com.android.application'
 apply plugin: 'com.google.protobuf'
-
 android {
-    compileSdkVersion 28
-    buildToolsVersion '28.0.3'
+    compileSdkVersion 26
+    buildToolsVersion '28.0.2'
 
-    compileOptions() {
-        sourceCompatibility JavaVersion.VERSION_1_8
-        targetCompatibility JavaVersion.VERSION_1_8
+    dexOptions {
+        preDexLibraries = false
+        additionalParameters=['--core-library']
+        javaMaxHeapSize "6g"
     }
-
+    android {
+        defaultConfig {
+            resConfigs "en"
+        }
+    }
     defaultConfig {
         minSdkVersion 23
-        resConfigs "en"
-        targetSdkVersion 28
+        targetSdkVersion 26
         versionCode 1
         versionName "1.0"
     }
-
     buildTypes {
         debug {
             minifyEnabled false
         }
-        release {
-            minifyEnabled true
-        }
     }
-
+    compileOptions() {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
     sourceSets {
         main {
             res.srcDirs = ['res']
@@ -57,18 +70,22 @@
     }
 }
 
+repositories {
+    mavenCentral()
+    jcenter()
+    google()
+}
+
+final String SUPPORT_LIBS_VERSION = '26.1.0'
 dependencies {
-    implementation      'androidx.leanback:leanback:1.1.0-alpha02'
-    implementation      'androidx.palette:palette:1.0.0'
-    implementation      'androidx.tvprovider:tvprovider:1.0.0'
-
-    annotationProcessor 'com.google.auto.value:auto-value:1.5.3'
-    implementation      'com.google.auto.value:auto-value:1.5.3'
-    implementation      'com.google.dagger:dagger:2.23'
-    implementation      'com.google.dagger:dagger-android:2.23'
-    annotationProcessor 'com.google.dagger:dagger-android-processor:2.23'
-    annotationProcessor 'com.google.dagger:dagger-compiler:2.23'
-
-    implementation      project(':common')
-    implementation      project(':tuner')
+    implementation 'com.google.android.exoplayer:exoplayer-core:2.9.0'
+    implementation 'com.google.android.exoplayer:exoplayer:r1.5.16'
+    implementation "com.android.support:palette-v7:${SUPPORT_LIBS_VERSION}"
+    implementation "com.android.support:leanback-v17:${SUPPORT_LIBS_VERSION}"
+    implementation "com.android.support:support-tv-provider:${SUPPORT_LIBS_VERSION}"
+    /*Not building with  latest one (1.6.2)*/
+    annotationProcessor 'com.google.auto.value:auto-value:1.5.4'
+    implementation 'com.google.auto.value:auto-value:1.5.4'
+    implementation project(':common')
+    implementation project(':tuner')
 }
diff --git a/tuner/SampleDvbTuner/robotests/javatests/com/android/tv/tuner/sample/dvb/util/SampleDvbConstantsTest.java b/tuner/SampleDvbTuner/robotests/javatests/com/android/tv/tuner/sample/dvb/util/SampleDvbConstantsTest.java
deleted file mode 100644
index 52fcffd..0000000
--- a/tuner/SampleDvbTuner/robotests/javatests/com/android/tv/tuner/sample/dvb/util/SampleDvbConstantsTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2019 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.sample.dvb.util;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.ComponentName;
-
-import androidx.test.core.app.ApplicationProvider;
-
-import com.android.tv.testing.constants.ConfigConstants;
-import com.android.tv.tuner.sample.dvb.tvinput.SampleDvbTunerTvInputService;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-/** Tests for {@link SampleDvbConstants}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-public class SampleDvbConstantsTest {
-
-    @Test
-    public void tunerInputId() {
-        assertThat(ComponentName.unflattenFromString(SampleDvbConstants.TUNER_INPUT_ID))
-                .isEqualTo(
-                        new ComponentName(
-                                ApplicationProvider.getApplicationContext(),
-                                SampleDvbTunerTvInputService.class));
-    }
-}
diff --git a/tuner/SampleDvbTuner/src/com/android/tv/tuner/sample/dvb/AndroidManifest.xml b/tuner/SampleDvbTuner/src/com/android/tv/tuner/sample/dvb/AndroidManifest.xml
index 8732b0d..dc04228 100644
--- a/tuner/SampleDvbTuner/src/com/android/tv/tuner/sample/dvb/AndroidManifest.xml
+++ b/tuner/SampleDvbTuner/src/com/android/tv/tuner/sample/dvb/AndroidManifest.xml
@@ -27,8 +27,6 @@
     <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
     <uses-permission android:name="com.android.providers.tv.permission.READ_EPG_DATA" />
     <uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA" />
-    <!-- Permission to modify Recorded Program -->
-    <uses-permission android:name="com.android.providers.tv.permission.ACCESS_ALL_EPG_DATA" />
 
     <!-- Permissions/feature for USB tuner -->
     <uses-permission android:name="android.permission.DVB_DEVICE" />
@@ -38,7 +36,7 @@
     <uses-feature android:name="android.software.leanback" android:required="true" />
     <uses-feature android:name="android.software.live_tv" android:required="true" />
     <uses-feature android:name="android.hardware.touchscreen" android:required="false"/>
-    <uses-sdk android:targetSdkVersion="28" android:minSdkVersion="23"/>
+    <uses-sdk android:targetSdkVersion="27" android:minSdkVersion="23"/>
     <application
         android:name=".app.SampleDvbTuner"
         android:icon="@mipmap/ic_launcher"
diff --git a/tuner/SampleDvbTuner/src/com/android/tv/tuner/sample/dvb/app/SampleDvbTuner.java b/tuner/SampleDvbTuner/src/com/android/tv/tuner/sample/dvb/app/SampleDvbTuner.java
index 5c9e842..568e3c9 100644
--- a/tuner/SampleDvbTuner/src/com/android/tv/tuner/sample/dvb/app/SampleDvbTuner.java
+++ b/tuner/SampleDvbTuner/src/com/android/tv/tuner/sample/dvb/app/SampleDvbTuner.java
@@ -18,18 +18,16 @@
 
 import android.content.ComponentName;
 import android.media.tv.TvContract;
-
 import com.android.tv.common.BaseApplication;
-import com.android.tv.common.dagger.ApplicationModule;
 import com.android.tv.common.singletons.HasSingletons;
 import com.android.tv.tuner.modules.TunerSingletonsModule;
 import com.android.tv.tuner.sample.dvb.singletons.SampleDvbSingletons;
 import com.android.tv.tuner.sample.dvb.tvinput.SampleDvbTunerTvInputService;
-
+import com.android.tv.tuner.tvinput.factory.TunerSessionFactory;
+import com.android.tv.tuner.tvinput.factory.TunerSessionFactoryImpl;
 import dagger.android.AndroidInjector;
-
 import com.android.tv.common.flags.CloudEpgFlags;
-
+import com.android.tv.common.flags.ConcurrentDvrPlaybackFlags;
 import javax.inject.Inject;
 
 /** The top level application for Sample DVB Tuner. */
@@ -38,6 +36,8 @@
 
     private String mEmbeddedInputId;
     @Inject CloudEpgFlags mCloudEpgFlags;
+    @Inject ConcurrentDvrPlaybackFlags mConcurrentDvrPlaybackFlags;
+    @Inject TunerSessionFactoryImpl mTunerSessionFactory;
 
     @Override
     public void onCreate() {
@@ -47,7 +47,7 @@
     @Override
     protected AndroidInjector<SampleDvbTuner> applicationInjector() {
         return DaggerSampleDvbTunerComponent.builder()
-                .applicationModule(new ApplicationModule(this))
+                .sampleDvbTunerModule(new SampleDvbTunerModule(this))
                 .tunerSingletonsModule(new TunerSingletonsModule(this))
                 .build();
     }
@@ -73,7 +73,16 @@
     }
 
     @Override
+    public ConcurrentDvrPlaybackFlags getConcurrentDvrPlaybackFlags() {
+        return mConcurrentDvrPlaybackFlags;
+    }
+
+    @Override
     public SampleDvbSingletons singletons() {
         return this;
     }
+
+    public TunerSessionFactory getTunerSessionFactory() {
+        return mTunerSessionFactory;
+    }
 }
diff --git a/tuner/SampleDvbTuner/src/com/android/tv/tuner/sample/dvb/app/SampleDvbTunerModule.java b/tuner/SampleDvbTuner/src/com/android/tv/tuner/sample/dvb/app/SampleDvbTunerModule.java
index aaaa101..4da3ca9 100644
--- a/tuner/SampleDvbTuner/src/com/android/tv/tuner/sample/dvb/app/SampleDvbTunerModule.java
+++ b/tuner/SampleDvbTuner/src/com/android/tv/tuner/sample/dvb/app/SampleDvbTunerModule.java
@@ -15,30 +15,38 @@
  */
 package com.android.tv.tuner.sample.dvb.app;
 
-import com.android.tv.common.dagger.ApplicationModule;
 import com.android.tv.common.flags.impl.DefaultFlagsModule;
 import com.android.tv.tuner.api.TunerFactory;
-import com.android.tv.tuner.dvb.DvbTunerHalFactory;
+import com.android.tv.tuner.builtin.BuiltInTunerHalFactory;
 import com.android.tv.tuner.modules.TunerModule;
 import com.android.tv.tuner.sample.dvb.setup.SampleDvbTunerSetupActivity;
 import com.android.tv.tuner.sample.dvb.tvinput.SampleDvbTunerTvInputService;
-
+import com.android.tv.tuner.tvinput.factory.TunerSessionFactory;
 import dagger.Module;
 import dagger.Provides;
 
 /** Dagger module for {@link SampleDvbTuner}. */
 @Module(
         includes = {
-            ApplicationModule.class,
             DefaultFlagsModule.class,
             SampleDvbTunerTvInputService.Module.class,
             SampleDvbTunerSetupActivity.Module.class,
             TunerModule.class,
         })
 class SampleDvbTunerModule {
+    private final SampleDvbTuner mSampleDvbTuner;
+
+    SampleDvbTunerModule(SampleDvbTuner sampleDvbTuner) {
+        mSampleDvbTuner = sampleDvbTuner;
+    }
+
+    @Provides
+    public TunerSessionFactory providesTunerSessionFactory() {
+        return mSampleDvbTuner.getTunerSessionFactory();
+    }
 
     @Provides
     TunerFactory providesTunerFactory() {
-        return DvbTunerHalFactory.INSTANCE;
+        return BuiltInTunerHalFactory.INSTANCE;
     }
 }
diff --git a/tuner/SampleDvbTuner/src/com/android/tv/tuner/sample/dvb/setup/SampleDvbTunerSetupActivity.java b/tuner/SampleDvbTuner/src/com/android/tv/tuner/sample/dvb/setup/SampleDvbTunerSetupActivity.java
index e2b5063..f9ef29c 100644
--- a/tuner/SampleDvbTuner/src/com/android/tv/tuner/sample/dvb/setup/SampleDvbTunerSetupActivity.java
+++ b/tuner/SampleDvbTuner/src/com/android/tv/tuner/sample/dvb/setup/SampleDvbTunerSetupActivity.java
@@ -36,7 +36,6 @@
 import com.android.tv.common.ui.setup.SetupMultiPaneFragment;
 import com.android.tv.common.util.PostalCodeUtils;
 import com.android.tv.tuner.sample.dvb.R;
-import com.android.tv.tuner.sample.dvb.util.SampleDvbConstants;
 import com.android.tv.tuner.setup.BaseTunerSetupActivity;
 import com.android.tv.tuner.setup.ConnectionTypeFragment;
 import com.android.tv.tuner.setup.LineupFragment;
@@ -56,7 +55,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
-/** An activity that serves Sample DVB tuner setup process. */
+/** An activity that serves Live TV tuner setup process. */
 public class SampleDvbTunerSetupActivity extends BaseTunerSetupActivity {
     private static final String TAG = "SampleDvbTunerSetupActivity";
     private static final boolean DEBUG = false;
@@ -79,10 +78,6 @@
     private final Runnable cancelFetchLineupTaskRunnable = this::cancelFetchLineup;
     private String embeddedInputId;
 
-    public SampleDvbTunerSetupActivity() {
-        super(SampleDvbConstants.TUNER_INPUT_ID);
-    }
-
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -198,7 +193,6 @@
             case ScanFragment.ACTION_CATEGORY:
                 switch (actionId) {
                     case ScanFragment.ACTION_CANCEL:
-                        clearTunerHal();
                         getFragmentManager().popBackStack();
                         return true;
                     case ScanFragment.ACTION_FINISH:
diff --git a/tuner/SampleDvbTuner/src/com/android/tv/tuner/sample/dvb/util/SampleDvbConstants.java b/tuner/SampleDvbTuner/src/com/android/tv/tuner/sample/dvb/util/SampleDvbConstants.java
deleted file mode 100644
index f7b34ce..0000000
--- a/tuner/SampleDvbTuner/src/com/android/tv/tuner/sample/dvb/util/SampleDvbConstants.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2019 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.sample.dvb.util;
-
-/** Static constants for Sample DVB Tuner */
-public final class SampleDvbConstants {
-
-    /** The Input ID for the embedded tuner in Sample DVB Tuner */
-    public static final String TUNER_INPUT_ID =
-            "com.android.tv.tuner.sample.dvb/.tvinput.SampleDvbTunerTvInputService";
-
-    private SampleDvbConstants() {}
-}
diff --git a/tuner/SampleNetworkTuner/AndroidManifest.xml b/tuner/SampleNetworkTuner/AndroidManifest.xml
index 22b0356..0ec9afc 100755
--- a/tuner/SampleNetworkTuner/AndroidManifest.xml
+++ b/tuner/SampleNetworkTuner/AndroidManifest.xml
@@ -19,19 +19,16 @@
 
     <uses-sdk
         android:minSdkVersion="23"
-        android:targetSdkVersion="28" />
+        android:targetSdkVersion="27" />
 
     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
-    <uses-permission android:name="android.permission.INTERNET" />
     <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="com.android.providers.tv.permission.READ_EPG_DATA" />
     <uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA" />
-    <!-- Permission to modify Recorded Program -->
-    <uses-permission android:name="com.android.providers.tv.permission.ACCESS_ALL_EPG_DATA" />
 
     <!-- Permissions/feature for USB tuner -->
     <uses-permission android:name="android.permission.DVB_DEVICE" />
diff --git a/tuner/SampleNetworkTuner/build.gradle b/tuner/SampleNetworkTuner/build.gradle
index 28ad3e4..657a425 100644
--- a/tuner/SampleNetworkTuner/build.gradle
+++ b/tuner/SampleNetworkTuner/build.gradle
@@ -19,35 +19,48 @@
  * Experimental gradle configuration.  This file may not be up to date.
  */
 
+buildscript {
+    repositories {
+        mavenCentral()
+        google()
+        jcenter()
+    }
+    dependencies {
+        classpath 'com.android.tools.build:gradle:3.1.4'
+        classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.5'
+    }
+}
 apply plugin: 'com.android.application'
 apply plugin: 'com.google.protobuf'
-
 android {
-    compileSdkVersion 28
-    buildToolsVersion '28.0.3'
+    compileSdkVersion 26
+    buildToolsVersion '28.0.2'
 
-    compileOptions() {
-        sourceCompatibility JavaVersion.VERSION_1_8
-        targetCompatibility JavaVersion.VERSION_1_8
+    dexOptions {
+        preDexLibraries = false
+        additionalParameters=['--core-library']
+        javaMaxHeapSize "6g"
     }
-
+    android {
+        defaultConfig {
+            resConfigs "en"
+        }
+    }
     defaultConfig {
         minSdkVersion 23
-        resConfigs "en"
-        targetSdkVersion 28
+        targetSdkVersion 26
         versionCode 1
         versionName "1.0"
     }
-
     buildTypes {
         debug {
             minifyEnabled false
         }
-        release {
-            minifyEnabled true
-        }
     }
-
+    compileOptions() {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
     sourceSets {
         main {
             res.srcDirs = ['res']
@@ -57,18 +70,22 @@
     }
 }
 
+repositories {
+    mavenCentral()
+    jcenter()
+    google()
+}
+
+final String SUPPORT_LIBS_VERSION = '26.1.0'
 dependencies {
-    implementation      'androidx.leanback:leanback:1.1.0-alpha02'
-    implementation      'androidx.palette:palette:1.0.0'
-    implementation      'androidx.tvprovider:tvprovider:1.0.0'
-
-    annotationProcessor 'com.google.auto.value:auto-value:1.5.3'
-    implementation      'com.google.auto.value:auto-value:1.5.3'
-    implementation      'com.google.dagger:dagger:2.23'
-    implementation      'com.google.dagger:dagger-android:2.23'
-    annotationProcessor 'com.google.dagger:dagger-android-processor:2.23'
-    annotationProcessor 'com.google.dagger:dagger-compiler:2.23'
-
-    implementation      project(':common')
-    implementation      project(':tuner')
+    implementation 'com.google.android.exoplayer:exoplayer-core:2.9.0'
+    implementation 'com.google.android.exoplayer:exoplayer:r1.5.16'
+    implementation "com.android.support:palette-v7:${SUPPORT_LIBS_VERSION}"
+    implementation "com.android.support:leanback-v17:${SUPPORT_LIBS_VERSION}"
+    implementation "com.android.support:support-tv-provider:${SUPPORT_LIBS_VERSION}"
+    /*Not building with  latest one (1.6.2)*/
+    annotationProcessor 'com.google.auto.value:auto-value:1.5.4'
+    implementation 'com.google.auto.value:auto-value:1.5.4'
+    implementation project(':common')
+    implementation project(':tuner')
 }
diff --git a/tuner/SampleNetworkTuner/robotests/javatests/com/android/tv/tuner/sample/network/util/SampleNetworkConstantsTest.java b/tuner/SampleNetworkTuner/robotests/javatests/com/android/tv/tuner/sample/network/util/SampleNetworkConstantsTest.java
deleted file mode 100644
index 5c860ef..0000000
--- a/tuner/SampleNetworkTuner/robotests/javatests/com/android/tv/tuner/sample/network/util/SampleNetworkConstantsTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2019 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.sample.network.util;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.ComponentName;
-
-import androidx.test.core.app.ApplicationProvider;
-
-import com.android.tv.testing.constants.ConfigConstants;
-import com.android.tv.tuner.sample.network.tvinput.SampleNetworkTunerTvInputService;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-/** Tests for {@link SampleNetworkConstants}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-public class SampleNetworkConstantsTest {
-
-    @Test
-    public void tunerInputId() {
-        assertThat(ComponentName.unflattenFromString(SampleNetworkConstants.TUNER_INPUT_ID))
-                .isEqualTo(
-                        new ComponentName(
-                                ApplicationProvider.getApplicationContext(),
-                                SampleNetworkTunerTvInputService.class));
-    }
-}
diff --git a/tuner/SampleNetworkTuner/src/com/android/tv/tuner/sample/network/AndroidManifest.xml b/tuner/SampleNetworkTuner/src/com/android/tv/tuner/sample/network/AndroidManifest.xml
index 7331391..dddd8a4 100644
--- a/tuner/SampleNetworkTuner/src/com/android/tv/tuner/sample/network/AndroidManifest.xml
+++ b/tuner/SampleNetworkTuner/src/com/android/tv/tuner/sample/network/AndroidManifest.xml
@@ -21,15 +21,12 @@
 
     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
-    <uses-permission android:name="android.permission.INTERNET"/>
     <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="com.android.providers.tv.permission.READ_EPG_DATA" />
     <uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA" />
-    <!-- Permission to modify Recorded Program -->
-    <uses-permission android:name="com.android.providers.tv.permission.ACCESS_ALL_EPG_DATA" />
 
     <!-- Permissions/feature for USB tuner -->
     <uses-permission android:name="android.permission.DVB_DEVICE" />
@@ -39,7 +36,7 @@
     <uses-feature android:name="android.software.leanback" android:required="true" />
     <uses-feature android:name="android.software.live_tv" android:required="true" />
     <uses-feature android:name="android.hardware.touchscreen" android:required="false"/>
-    <uses-sdk android:targetSdkVersion="28" android:minSdkVersion="23"/>
+    <uses-sdk android:targetSdkVersion="27" android:minSdkVersion="23"/>
     <application
         android:name=".app.SampleNetworkTuner"
         android:icon="@mipmap/ic_launcher"
diff --git a/tuner/SampleNetworkTuner/src/com/android/tv/tuner/sample/network/app/SampleNetworkTuner.java b/tuner/SampleNetworkTuner/src/com/android/tv/tuner/sample/network/app/SampleNetworkTuner.java
index 0f9d24e..eb5b2ad 100644
--- a/tuner/SampleNetworkTuner/src/com/android/tv/tuner/sample/network/app/SampleNetworkTuner.java
+++ b/tuner/SampleNetworkTuner/src/com/android/tv/tuner/sample/network/app/SampleNetworkTuner.java
@@ -18,18 +18,16 @@
 
 import android.content.ComponentName;
 import android.media.tv.TvContract;
-
 import com.android.tv.common.BaseApplication;
-import com.android.tv.common.dagger.ApplicationModule;
 import com.android.tv.common.singletons.HasSingletons;
 import com.android.tv.tuner.modules.TunerSingletonsModule;
 import com.android.tv.tuner.sample.network.singletons.SampleNetworkSingletons;
 import com.android.tv.tuner.sample.network.tvinput.SampleNetworkTunerTvInputService;
-
+import com.android.tv.tuner.tvinput.factory.TunerSessionFactory;
+import com.android.tv.tuner.tvinput.factory.TunerSessionFactoryImpl;
 import dagger.android.AndroidInjector;
-
 import com.android.tv.common.flags.CloudEpgFlags;
-
+import com.android.tv.common.flags.ConcurrentDvrPlaybackFlags;
 import javax.inject.Inject;
 
 /** The top level application for Sample DVB Tuner. */
@@ -38,6 +36,8 @@
 
     private String mEmbeddedInputId;
     @Inject CloudEpgFlags mCloudEpgFlags;
+    @Inject ConcurrentDvrPlaybackFlags mConcurrentDvrPlaybackFlags;
+    @Inject TunerSessionFactoryImpl mTunerSessionFactory;
 
     @Override
     public void onCreate() {
@@ -47,7 +47,7 @@
     @Override
     protected AndroidInjector<SampleNetworkTuner> applicationInjector() {
         return DaggerSampleNetworkTunerComponent.builder()
-                .applicationModule(new ApplicationModule(this))
+                .sampleNetworkTunerModule(new SampleNetworkTunerModule(this))
                 .tunerSingletonsModule(new TunerSingletonsModule(this))
                 .build();
     }
@@ -73,7 +73,16 @@
     }
 
     @Override
+    public ConcurrentDvrPlaybackFlags getConcurrentDvrPlaybackFlags() {
+        return mConcurrentDvrPlaybackFlags;
+    }
+
+    @Override
     public SampleNetworkSingletons singletons() {
         return this;
     }
+
+    public TunerSessionFactory getTunerSessionFactory() {
+        return mTunerSessionFactory;
+    }
 }
diff --git a/tuner/SampleNetworkTuner/src/com/android/tv/tuner/sample/network/app/SampleNetworkTunerModule.java b/tuner/SampleNetworkTuner/src/com/android/tv/tuner/sample/network/app/SampleNetworkTunerModule.java
index 3fa4502..d974e20 100644
--- a/tuner/SampleNetworkTuner/src/com/android/tv/tuner/sample/network/app/SampleNetworkTunerModule.java
+++ b/tuner/SampleNetworkTuner/src/com/android/tv/tuner/sample/network/app/SampleNetworkTunerModule.java
@@ -15,30 +15,38 @@
  */
 package com.android.tv.tuner.sample.network.app;
 
-import com.android.tv.common.dagger.ApplicationModule;
 import com.android.tv.common.flags.impl.DefaultFlagsModule;
 import com.android.tv.tuner.api.TunerFactory;
-import com.android.tv.tuner.hdhomerun.HdHomeRunTunerHalFactory;
+import com.android.tv.tuner.builtin.BuiltInTunerHalFactory;
 import com.android.tv.tuner.modules.TunerModule;
 import com.android.tv.tuner.sample.network.setup.SampleNetworkTunerSetupActivity;
 import com.android.tv.tuner.sample.network.tvinput.SampleNetworkTunerTvInputService;
-
+import com.android.tv.tuner.tvinput.factory.TunerSessionFactory;
 import dagger.Module;
 import dagger.Provides;
 
 /** Dagger module for {@link SampleNetworkTuner}. */
 @Module(
         includes = {
-            ApplicationModule.class,
             DefaultFlagsModule.class,
             SampleNetworkTunerTvInputService.Module.class,
             SampleNetworkTunerSetupActivity.Module.class,
             TunerModule.class,
         })
 class SampleNetworkTunerModule {
+    private final SampleNetworkTuner mSampleNetworkTuner;
+
+    SampleNetworkTunerModule(SampleNetworkTuner sampleNetworkTuner) {
+        mSampleNetworkTuner = sampleNetworkTuner;
+    }
+
+    @Provides
+    public TunerSessionFactory providesTunerSessionFactory() {
+        return mSampleNetworkTuner.getTunerSessionFactory();
+    }
 
     @Provides
     TunerFactory providesTunerFactory() {
-        return HdHomeRunTunerHalFactory.INSTANCE;
+        return BuiltInTunerHalFactory.INSTANCE;
     }
 }
diff --git a/tuner/SampleNetworkTuner/src/com/android/tv/tuner/sample/network/setup/SampleNetworkTunerSetupActivity.java b/tuner/SampleNetworkTuner/src/com/android/tv/tuner/sample/network/setup/SampleNetworkTunerSetupActivity.java
index 755e0bb..fd783c4 100644
--- a/tuner/SampleNetworkTuner/src/com/android/tv/tuner/sample/network/setup/SampleNetworkTunerSetupActivity.java
+++ b/tuner/SampleNetworkTuner/src/com/android/tv/tuner/sample/network/setup/SampleNetworkTunerSetupActivity.java
@@ -36,7 +36,6 @@
 import com.android.tv.common.ui.setup.SetupMultiPaneFragment;
 import com.android.tv.common.util.PostalCodeUtils;
 import com.android.tv.tuner.sample.network.R;
-import com.android.tv.tuner.sample.network.util.SampleNetworkConstants;
 import com.android.tv.tuner.setup.BaseTunerSetupActivity;
 import com.android.tv.tuner.setup.ConnectionTypeFragment;
 import com.android.tv.tuner.setup.LineupFragment;
@@ -56,7 +55,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
-/** An activity that serves TV app tuner setup process. */
+/** An activity that serves Live TV tuner setup process. */
 public class SampleNetworkTunerSetupActivity extends BaseTunerSetupActivity {
     private static final String TAG = "SampleNetworkTunerSetupActivity";
     private static final boolean DEBUG = false;
@@ -79,10 +78,6 @@
     private final Runnable cancelFetchLineupTaskRunnable = this::cancelFetchLineup;
     private String embeddedInputId;
 
-    public SampleNetworkTunerSetupActivity() {
-        super(SampleNetworkConstants.TUNER_INPUT_ID);
-    }
-
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
diff --git a/tuner/SampleNetworkTuner/src/com/android/tv/tuner/sample/network/util/SampleNetworkConstants.java b/tuner/SampleNetworkTuner/src/com/android/tv/tuner/sample/network/util/SampleNetworkConstants.java
deleted file mode 100644
index d0a8d25..0000000
--- a/tuner/SampleNetworkTuner/src/com/android/tv/tuner/sample/network/util/SampleNetworkConstants.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2019 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.sample.network.util;
-
-/** Static constants for Sample Network Tuner */
-public final class SampleNetworkConstants {
-
-    /** The Input ID for the embedded tuner in Sample Network Tuner */
-    public static final String TUNER_INPUT_ID =
-            "com.android.tv.tuner.sample.network/.tvinput.SampleNetworkTunerTvInputService";
-
-    private SampleNetworkConstants() {}
-}
diff --git a/tuner/build.gradle b/tuner/build.gradle
index b00b460..0f40a29 100644
--- a/tuner/build.gradle
+++ b/tuner/build.gradle
@@ -21,24 +21,39 @@
 
 apply plugin: 'com.android.library'
 apply plugin: 'com.google.protobuf'
-
+buildscript {
+    repositories {
+        mavenCentral()
+        google()
+        jcenter()
+    }
+    dependencies {
+        classpath 'com.android.tools.build:gradle:3.1.4'
+        classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.5'
+    }
+}
 android {
-    compileSdkVersion 28
-    buildToolsVersion '28.0.3'
+    compileSdkVersion 26
+    buildToolsVersion '28.0.2'
 
-    compileOptions() {
-        sourceCompatibility JavaVersion.VERSION_1_8
-        targetCompatibility JavaVersion.VERSION_1_8
+    dexOptions {
+        preDexLibraries = false
+        additionalParameters = ['--core-library']
+        javaMaxHeapSize "6g"
+    }
+
+    android {
+        defaultConfig {
+            resConfigs "en"
+        }
     }
 
     defaultConfig {
         minSdkVersion 23
-        resConfigs "en"
-        targetSdkVersion 28
+        targetSdkVersion 26
         versionCode 1
         versionName "1.0"
     }
-
     buildTypes {
         debug {
             minifyEnabled false
@@ -47,6 +62,10 @@
             minifyEnabled true
         }
     }
+    compileOptions() {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
 
     sourceSets {
         main {
@@ -54,54 +73,43 @@
             java.srcDirs = ['src']
             manifest.srcFile 'AndroidManifest.xml'
             proto {
-                srcDir 'proto/src/main/proto'
+                srcDir 'proto/'
             }
         }
     }
 }
 
+repositories {
+    mavenCentral()
+    google()
+    jcenter()
+}
+
+final String SUPPORT_LIBS_VERSION = '26.1.0'
 dependencies {
-    implementation      'androidx.annotation:annotation:1.1.0'
-    implementation      'androidx.appcompat:appcompat:1.0.2'
-    implementation      'androidx.leanback:leanback:1.1.0-alpha02'
-    implementation      'androidx.recyclerview:recyclerview:1.0.0'
-    implementation      'androidx.recyclerview:recyclerview-selection:1.0.0'
-    implementation      'androidx.tvprovider:tvprovider:1.0.0'
-
-    implementation      'com.google.android.exoplayer:exoplayer:r1.5.16'
-    api                 'com.google.android.exoplayer:exoplayer-core:2.10.1'
-    annotationProcessor 'com.google.auto.factory:auto-factory:1.0-beta6'
-    implementation      'com.google.auto.factory:auto-factory:1.0-beta6'
-    implementation      'com.google.dagger:dagger:2.23'
-    implementation      'com.google.dagger:dagger-android:2.23'
-    annotationProcessor 'com.google.dagger:dagger-android-processor:2.23'
-    annotationProcessor 'com.google.dagger:dagger-compiler:2.23'
-    implementation      'com.google.guava:guava:28.0-jre'
-    implementation      'com.google.protobuf:protobuf-java:3.0.0'
-
-    implementation      project(':common')
+    implementation 'com.google.android.exoplayer:exoplayer-core:2.9.0'
+    implementation 'com.google.android.exoplayer:exoplayer:r1.5.16'
+    implementation "com.android.support:support-tv-provider:${SUPPORT_LIBS_VERSION}"
+    implementation "com.android.support:appcompat-v7:${SUPPORT_LIBS_VERSION}"
+    implementation "com.android.support:leanback-v17:${SUPPORT_LIBS_VERSION}"
+    implementation 'com.google.guava:guava:26.0-android'
+    implementation 'com.google.protobuf.nano:protobuf-javanano:3.2.0rc2'
+    implementation project(':common')
 }
 protobuf {
     // Configure the protoc executable
     protoc {
-        artifact = 'com.google.protobuf:protoc:3.0.0'
-
-        plugins {
-            javalite {
-                // The codegen for lite comes as a separate artifact
-                artifact = 'com.google.protobuf:protoc-gen-javalite:3.0.0'
-            }
-        }
+        artifact = 'com.google.protobuf:protoc:3.1.0'
 
         generateProtoTasks {
             all().each {
                 task -> task.builtins {
                     remove java
-                }
-                    task.plugins {
-                        javalite {}
+                    javanano {
+                        option "enum_style=java"
                     }
+                }
             }
         }
     }
-}
+}
\ No newline at end of file
diff --git a/tuner/proto/Android.bp b/tuner/proto/Android.bp
index d1728a6..67f35f8 100644
--- a/tuner/proto/Android.bp
+++ b/tuner/proto/Android.bp
@@ -19,7 +19,8 @@
     srcs: ["*.proto"],
     sdk_version: "system_current",
     proto: {
-        type: "lite",
+        type: "nano",
+        output_params: ["enum_style=java"],
         canonical_path_from_root: false,
     },
     min_sdk_version: "23",
diff --git a/tuner/proto/channel.proto b/tuner/proto/channel.proto
index 815ffbc..ff372ad 100644
--- a/tuner/proto/channel.proto
+++ b/tuner/proto/channel.proto
@@ -18,13 +18,18 @@
 
 package com.android.tv.tuner.data;
 
-import "track.proto";
-
 option java_package = "com.android.tv.tuner.data";
 option java_outer_classname = "Channel";
 
+
+// AOSP_Comment_Out import "third_party/android/nanoproto/nano_descriptor.proto";
+
+import "track.proto";
+
 // Holds information about a channel used in the tuners.
 message TunerChannelProto {
+// AOSP_Comment_Out   option (proto2.nano.message_as_lite) = false;
+
   optional TunerType type = 1;
   optional string short_name = 2;
   optional string long_name = 3;
@@ -46,24 +51,22 @@
   optional int32 audio_track_index = 19;
   repeated AtscCaptionTrack caption_tracks = 20;
   optional bool has_caption_track = 21;
-  optional AtscServiceType service_type = 22
-      [default = SERVICE_TYPE_ATSC_DIGITAL_TELEVISION];
+  optional AtscServiceType service_type = 22 [default = SERVICE_TYPE_ATSC_DIGITAL_TELEVISION];
   optional bool recording_prohibited = 23;
   optional string video_format = 24;
   /**
    * The flag indicating whether this TV channel is locked or not.
-   * This is primarily used for alternative parental control to prevent
-   * unauthorized users from watching the current channel regardless of the
-   * content rating
-   * @see <a
-   * href="https://developer.android.com/reference/android/media/tv/TvContract.Channels.html#COLUMN_LOCKED">link</a>
+   * This is primarily used for alternative parental control to prevent unauthorized users from
+   * watching the current channel regardless of the content rating
+   * @see <a href="https://developer.android.com/reference/android/media/tv/TvContract.Channels.html#COLUMN_LOCKED">link</a>
    */
   optional bool locked = 25;
-  optional DeliverySystemType delivery_system_type = 26;
 }
 
 // Enum describing the types of tuner.
 enum TunerType {
+// AOSP_Comment_Out   option (proto2.nano.enum_as_lite) = false;
+
   TYPE_TUNER = 0;
   TYPE_FILE = 1;
   TYPE_NETWORK = 2;
@@ -71,10 +74,8 @@
 
 // Enum describing the types of video stream.
 enum VideoStreamType {
-  // Default unset value.  The spec says 0 is reserved.
-  UNSET = 0x00;
-  // DEPRECATED: previously used as default or unset value
-  INVALID_STREAMTYPE = -1 [deprecated=true];
+// AOSP_Comment_Out   option (proto2.nano.enum_as_lite) = false;
+
   // ISO/IEC 11172 Video (MPEG-1)
   MPEG1 = 0x01;
   // ISO/IEC 13818-2 (MPEG-2) Video
@@ -89,6 +90,8 @@
 
 // Enum describing the types of audio stream.
 enum AudioStreamType {
+// AOSP_Comment_Out   option (proto2.nano.enum_as_lite) = false;
+
   // ISO/IEC 11172 Audio (MPEG-1)
   MPEG1AUDIO = 0x03;
   // ISO/IEC 13818-3 Audio (MPEG-2)
@@ -106,6 +109,8 @@
 // Enum describing ATSC service types
 // See ATSC Code Points Registry.
 enum AtscServiceType {
+// AOSP_Comment_Out   option (proto2.nano.enum_as_lite) = false;
+
   SERVICE_TYPE_ATSC_RESERVED = 0x0;
   SERVICE_TYPE_ANALOG_TELEVISION_CHANNELS = 0x1;
   SERVICE_TYPE_ATSC_DIGITAL_TELEVISION = 0x2;
@@ -117,15 +122,3 @@
   SERVICE_TYPE_ATSC_NRT_SERVICE = 0x8;
   SERVICE_TYPE_EXTENDED_PARAMERTERIZED_SERVICE = 0x9;
 }
-
-// Enum describing the types of delivery system.
-enum DeliverySystemType {
-  // Do not reorder. Must match Tuner.java
-  DELIVERY_SYSTEM_UNDEFINED = 0;
-  DELIVERY_SYSTEM_ATSC = 1;
-  DELIVERY_SYSTEM_DVBC = 2;
-  DELIVERY_SYSTEM_DVBS = 3;
-  DELIVERY_SYSTEM_DVBS2 = 4;
-  DELIVERY_SYSTEM_DVBT = 5;
-  DELIVERY_SYSTEM_DVBT2 = 6;
-}
diff --git a/tuner/proto/track.proto b/tuner/proto/track.proto
index a4a20db..11ca784 100644
--- a/tuner/proto/track.proto
+++ b/tuner/proto/track.proto
@@ -18,11 +18,15 @@
 
 package com.android.tv.tuner.data;
 
+// AOSP_Comment_Out import "third_party/android/nanoproto/nano_descriptor.proto";
+
 option java_package = "com.android.tv.tuner.data";
 option java_outer_classname = "Track";
 
 // Represents a AC3 audio track.
 message AtscAudioTrack {
+// AOSP_Comment_Out   option (proto2.nano.message_as_lite) = false; 
+
   optional string language = 1;
   optional AudioType audio_type = 2;
   optional int32 index = 3;
@@ -32,6 +36,8 @@
   // Enum describing the types of a audio track.
   // See ISO/IEC 138181-1:2000(e) Table 2-53.
   enum AudioType {
+// AOSP_Comment_Out     option (proto2.nano.enum_as_lite) = false;
+
     AUDIOTYPE_UNDEFINED = 0;
     AUDIOTYPE_CLEAN_EFFECTS = 1;
     AUDIOTYPE_HEARING_IMPAIRED = 2;
@@ -41,8 +47,11 @@
 
 // Represents a CEA-708 caption track.
 message AtscCaptionTrack {
+// AOSP_Comment_Out   option (proto2.nano.message_as_lite) = false;
+
   optional string language = 1;
   optional int32 service_number = 2;
   optional bool easy_reader = 3;
   optional bool wide_aspect_ratio = 4;
 }
+
diff --git a/tuner/res/layout/guided_action_editable.xml b/tuner/res/layout/guided_action_editable.xml
index 4d3c87f..84f56f8 100644
--- a/tuner/res/layout/guided_action_editable.xml
+++ b/tuner/res/layout/guided_action_editable.xml
@@ -15,13 +15,13 @@
   ~ limitations under the License.
   -->
 
-<androidx.leanback.widget.GuidedActionItemContainer
+<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">
 
-    <androidx.leanback.widget.NonOverlappingLinearLayout
+    <android.support.v17.leanback.widget.NonOverlappingLinearLayout
         android:id="@+id/guidedactions_item_content"
         style="?attr/guidedActionItemContentStyle" >
 
@@ -32,10 +32,10 @@
             android:textColor="@color/lb_guidedactions_item_unselected_text_color"
             android:textSize="16sp" />
 
-        <androidx.leanback.widget.GuidedActionEditText
+        <android.support.v17.leanback.widget.GuidedActionEditText
             android:id="@+id/guidedactions_item_description"
             style="?attr/guidedActionItemDescriptionStyle" />
 
-    </androidx.leanback.widget.NonOverlappingLinearLayout>
+    </android.support.v17.leanback.widget.NonOverlappingLinearLayout>
 
-</androidx.leanback.widget.GuidedActionItemContainer>
\ No newline at end of file
+</android.support.v17.leanback.widget.GuidedActionItemContainer>
\ No newline at end of file
diff --git a/tuner/res/raw/ut_euro_dvbt_all b/tuner/res/raw/ut_euro_dvbt_all
index a2ff03b..101ee3e 100644
--- a/tuner/res/raw/ut_euro_dvbt_all
+++ b/tuner/res/raw/ut_euro_dvbt_all
@@ -1,6 +1,66 @@
 # 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
@@ -70,7 +130,6 @@
 T 562167000 QAM16
 T 569833000 QAM64
 T 570000000 QAM16
-T 570000000 QAM64
 T 570167000 QAM16
 T 577833000 QAM16
 T 578000000 QAM16
@@ -79,9 +138,7 @@
 T 578167000 QAM16
 T 578167000 QAM64
 T 586000000 QAM16
-T 586000000 QAM256
 T 594000000 QAM16
-T 594000000 QAM64
 T 602000000 QAM16
 T 602000000 QAM64
 T 610000000 QAM16
@@ -167,13 +224,11 @@
 T 746000000 QAM16
 T 746000000 QAM64
 T 746000000 QPSK
-T 746000000 QAM256
 T 746167000 QAM64
 T 753833000 QAM16
 T 753833000 QAM64
 T 754000000 QAM16
 T 754000000 QAM64
-T 754000000 QAM256
 T 754167000 QAM16
 T 761833000 QAM16
 T 761833000 QAM64
diff --git a/tuner/src/com/android/tv/tuner/dvb/DvbDeviceAccessor.java b/tuner/src/com/android/tv/tuner/DvbDeviceAccessor.java
similarity index 99%
rename from tuner/src/com/android/tv/tuner/dvb/DvbDeviceAccessor.java
rename to tuner/src/com/android/tv/tuner/DvbDeviceAccessor.java
index 8be27c9..217433d 100644
--- a/tuner/src/com/android/tv/tuner/dvb/DvbDeviceAccessor.java
+++ b/tuner/src/com/android/tv/tuner/DvbDeviceAccessor.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.tv.tuner.dvb;
+package com.android.tv.tuner;
 
 import android.content.Context;
 import android.media.tv.TvInputManager;
diff --git a/tuner/src/com/android/tv/tuner/dvb/DvbTunerHal.java b/tuner/src/com/android/tv/tuner/DvbTunerHal.java
similarity index 97%
rename from tuner/src/com/android/tv/tuner/dvb/DvbTunerHal.java
rename to tuner/src/com/android/tv/tuner/DvbTunerHal.java
index 7f68e37..c802ebb 100644
--- a/tuner/src/com/android/tv/tuner/dvb/DvbTunerHal.java
+++ b/tuner/src/com/android/tv/tuner/DvbTunerHal.java
@@ -14,14 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.tv.tuner.dvb;
+package com.android.tv.tuner;
 
 import android.content.Context;
 import android.os.ParcelFileDescriptor;
 import android.util.Log;
 import com.android.tv.common.compat.TvInputConstantCompat;
-import com.android.tv.tuner.TunerHal;
-import com.android.tv.tuner.dvb.DvbDeviceAccessor.DvbDeviceInfoWrapper;
+import com.android.tv.tuner.DvbDeviceAccessor.DvbDeviceInfoWrapper;
 import java.util.List;
 import java.util.SortedSet;
 import java.util.TreeSet;
diff --git a/tuner/src/com/android/tv/tuner/TunerHal.java b/tuner/src/com/android/tv/tuner/TunerHal.java
index 3f469d6..dce4f4c 100644
--- a/tuner/src/com/android/tv/tuner/TunerHal.java
+++ b/tuner/src/com/android/tv/tuner/TunerHal.java
@@ -36,7 +36,6 @@
     private static final int DEFAULT_QAM_TUNE_TIMEOUT_MS = 4000; // Some device takes time for
 
     @DeliverySystemType private int mDeliverySystemType;
-    @DeliverySystemType private int[] mDeliverySystemTypes;
     private boolean mIsStreaming;
     private int mFrequency;
     private String mModulation;
@@ -58,16 +57,9 @@
     }
 
     protected void getDeliverySystemTypeFromDevice() {
-        getDeliverySystemTypesFromDevice();
-    }
-
-    protected void getDeliverySystemTypesFromDevice() {
         if (mDeliverySystemType == DELIVERY_SYSTEM_UNDEFINED) {
             mDeliverySystemType = nativeGetDeliverySystemType(getDeviceId());
         }
-        if (mDeliverySystemTypes == null) {
-            mDeliverySystemTypes = nativeGetDeliverySystemTypes(getDeviceId());
-        }
     }
 
     /**
@@ -87,34 +79,18 @@
 
     protected native void nativeFinalize(long deviceId);
 
-    @Override
-    public synchronized boolean tune(
-                int frequency, @ModulationType String modulation,
-            String channelNumber) {
-        return tuneInternal(mDeliverySystemType, frequency, modulation, channelNumber);
-    }
-
-    @Override
-    public synchronized boolean tune(
-            int deliverySystemType, int frequency, @ModulationType String modulation,
-            String channelNumber) {
-        return tuneInternal(deliverySystemType, frequency, modulation, channelNumber);
-    }
-
     /**
      * Sets the tuner channel. This should be called after acquiring a tuner device.
      *
-     * @param deliverySystemType a system delivery type of the channel to tune to
      * @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
      */
-    protected boolean tuneInternal(
-        int deliverySystemType, int frequency, @ModulationType String modulation,
-        String channelNumber) {
-
+    @Override
+    public synchronized boolean tune(
+            int frequency, @ModulationType String modulation, String channelNumber) {
         if (!isDeviceOpen()) {
             Log.e(TAG, "There's no available device");
             return false;
@@ -123,76 +99,40 @@
             nativeCloseAllPidFilters(getDeviceId());
             mIsStreaming = false;
         }
-        if (mDeliverySystemTypes != null) {
-            int i;
-            for (i = 0; i < mDeliverySystemTypes.length; i++) {
-                if (deliverySystemType == mDeliverySystemTypes[i]) {
-                    break;
-                }
-            }
-
-            if (i == mDeliverySystemTypes.length) {
-                Log.e(TAG, "Unsupported delivery system type for device");
-                return false;
-            }
-        }
 
         // When tuning to a new channel in the same frequency, there's no need to stop current tuner
         // device completely and the only thing necessary for tuning is reopening pid filters.
         if (mFrequency == frequency && Objects.equals(mModulation, modulation)) {
             addPidFilter(PID_PAT, FILTER_TYPE_OTHER);
             addPidFilter(PID_ATSC_SI_BASE, FILTER_TYPE_OTHER);
-            if (Tuner.isDvbDeliverySystem(deliverySystemType)) {
+            if (Tuner.isDvbDeliverySystem(mDeliverySystemType)) {
                 addPidFilter(PID_DVB_SDT, FILTER_TYPE_OTHER);
                 addPidFilter(PID_DVB_EIT, FILTER_TYPE_OTHER);
             }
             mIsStreaming = true;
             return true;
         }
-
         int timeout_ms =
                 modulation.equals(MODULATION_8VSB)
                         ? DEFAULT_VSB_TUNE_TIMEOUT_MS
                         : DEFAULT_QAM_TUNE_TIMEOUT_MS;
-
-        boolean tuneStatus;
-        switch(deliverySystemType) {
-            case DELIVERY_SYSTEM_UNDEFINED:
-            case DELIVERY_SYSTEM_ATSC:
-                tuneStatus = nativeTune(getDeviceId(), frequency, modulation, timeout_ms);
-                break;
-            case DELIVERY_SYSTEM_DVBT:
-            case DELIVERY_SYSTEM_DVBT2:
-                tuneStatus = nativeTune(getDeviceId(), deliverySystemType, frequency, modulation,
-                        timeout_ms);
-                break;
-            default:
-                Log.e(TAG, "Unsupported delivery system type for device");
-                return false;
-        }
-
-        if (tuneStatus == true) {
+        if (nativeTune(getDeviceId(), frequency, modulation, timeout_ms)) {
             addPidFilter(PID_PAT, FILTER_TYPE_OTHER);
             addPidFilter(PID_ATSC_SI_BASE, FILTER_TYPE_OTHER);
-            if (Tuner.isDvbDeliverySystem(deliverySystemType)) {
+            if (Tuner.isDvbDeliverySystem(mDeliverySystemType)) {
                 addPidFilter(PID_DVB_SDT, FILTER_TYPE_OTHER);
                 addPidFilter(PID_DVB_EIT, FILTER_TYPE_OTHER);
             }
             mFrequency = frequency;
             mModulation = modulation;
             mIsStreaming = true;
+            return true;
         }
-
-        return tuneStatus;
+        return false;
     }
 
     protected native boolean nativeTune(
-            long deviceId, int frequency,
-            @ModulationType String modulation, int timeout_ms);
-
-    protected native boolean nativeTune(
-            long deviceId, int deliverySystemType, int frequency,
-            @ModulationType String modulation, int timeout_ms);
+            long deviceId, int frequency, @ModulationType String modulation, int timeout_ms);
 
     /**
      * Sets a pid filter. This should be set after setting a channel.
@@ -222,8 +162,6 @@
 
     protected native int nativeGetDeliverySystemType(long deviceId);
 
-    protected native int[] nativeGetDeliverySystemTypes(long deviceId);
-
     protected native int nativeGetSignalStrength(long deviceId);
 
     /**
@@ -253,11 +191,6 @@
         return mDeliverySystemType;
     }
 
-    @Override
-    public int[] getDeliverySystemTypes() {
-        return mDeliverySystemTypes;
-    }
-
     protected native void nativeStopTune(long deviceId);
 
     /**
diff --git a/tuner/src/com/android/tv/tuner/api/ScanChannel.java b/tuner/src/com/android/tv/tuner/api/ScanChannel.java
index 1c7a6e7..56e5493 100644
--- a/tuner/src/com/android/tv/tuner/api/ScanChannel.java
+++ b/tuner/src/com/android/tv/tuner/api/ScanChannel.java
@@ -15,15 +15,11 @@
  */
 package com.android.tv.tuner.api;
 
-import android.util.Log;
-import com.android.tv.tuner.data.Channel;
-
+import com.android.tv.tuner.data.nano.Channel;
 
 /** Channel information gathered from a <em>scan</em> */
 public final class ScanChannel {
-    private static final String TAG = "ScanChannel";
     public final int type;
-    public final Channel.DeliverySystemType deliverySystemType;
     public final int frequency;
     public final String modulation;
     public final String filename;
@@ -35,60 +31,25 @@
     public final Integer radioFrequencyNumber;
 
     public static ScanChannel forTuner(
-            String deliverySystemType, int frequency, String modulation,
-            Integer radioFrequencyNumber) {
+            int frequency, String modulation, Integer radioFrequencyNumber) {
         return new ScanChannel(
-                Channel.TunerType.TYPE_TUNER_VALUE, lookupDeliveryStringToInt(deliverySystemType),
-                frequency, modulation, null, radioFrequencyNumber);
+                Channel.TunerType.TYPE_TUNER, frequency, modulation, null, radioFrequencyNumber);
     }
 
     public static ScanChannel forFile(int frequency, String filename) {
-        return new ScanChannel(Channel.TunerType.TYPE_FILE_VALUE,
-                Channel.DeliverySystemType.DELIVERY_SYSTEM_UNDEFINED, frequency, "file:",
-                filename, null);
+        return new ScanChannel(Channel.TunerType.TYPE_FILE, frequency, "file:", filename, null);
     }
 
     private ScanChannel(
             int type,
-            Channel.DeliverySystemType deliverySystemType,
             int frequency,
             String modulation,
             String filename,
             Integer radioFrequencyNumber) {
         this.type = type;
-        this.deliverySystemType = deliverySystemType;
         this.frequency = frequency;
         this.modulation = modulation;
         this.filename = filename;
         this.radioFrequencyNumber = radioFrequencyNumber;
     }
-
-    private static Channel.DeliverySystemType lookupDeliveryStringToInt(String deliverySystemType) {
-        Channel.DeliverySystemType ret;
-        switch (deliverySystemType) {
-            case "A":
-                ret = Channel.DeliverySystemType.DELIVERY_SYSTEM_ATSC;
-                break;
-            case "C":
-                ret = Channel.DeliverySystemType.DELIVERY_SYSTEM_DVBC;
-                break;
-            case "S":
-                ret = Channel.DeliverySystemType.DELIVERY_SYSTEM_DVBS;
-                break;
-            case "S2":
-                ret = Channel.DeliverySystemType.DELIVERY_SYSTEM_DVBS2;
-                break;
-            case "T":
-                ret = Channel.DeliverySystemType.DELIVERY_SYSTEM_DVBT;
-                break;
-            case "T2":
-                ret = Channel.DeliverySystemType.DELIVERY_SYSTEM_DVBT2;
-                break;
-            default:
-                Log.e(TAG, "Unknown delivery system type");
-                ret = Channel.DeliverySystemType.DELIVERY_SYSTEM_UNDEFINED;
-                break;
-        }
-        return ret;
-    }
 }
diff --git a/tuner/src/com/android/tv/tuner/api/Tuner.java b/tuner/src/com/android/tv/tuner/api/Tuner.java
index 02df3ca..6f7e9d9 100644
--- a/tuner/src/com/android/tv/tuner/api/Tuner.java
+++ b/tuner/src/com/android/tv/tuner/api/Tuner.java
@@ -28,8 +28,6 @@
     int FILTER_TYPE_VIDEO = 2;
     int FILTER_TYPE_PCR = 3;
     String MODULATION_8VSB = "8VSB";
-    String MODULATION_QAM16 = "QAM16";
-    String MODULATION_QAM64 = "QAM64";
     String MODULATION_QAM256 = "QAM256";
     int DELIVERY_SYSTEM_UNDEFINED = 0;
     int DELIVERY_SYSTEM_ATSC = 1;
@@ -42,7 +40,6 @@
     int TUNER_TYPE_USB = 2;
     int TUNER_TYPE_NETWORK = 3;
     int BUILT_IN_TUNER_TYPE_LINUX_DVB = 1;
-    int BUILT_IN_TUNER_TYPE_ARCHER = 100;
 
     /** Check a delivery system is for DVB or not. */
     static boolean isDvbDeliverySystem(@DeliverySystemType int deliverySystemType) {
@@ -69,11 +66,6 @@
 
     boolean tune(int frequency, @ModulationType String modulation, String channelNumber);
 
-    default boolean tune(@DeliverySystemType int deliverySystemType, int frequency,
-                 @ModulationType String modulation, String channelNumber) {
-      return tune(frequency, modulation, channelNumber);
-    }
-
     boolean addPidFilter(int pid, @FilterType int filterType);
 
     void stopTune();
@@ -81,10 +73,6 @@
     void setHasPendingTune(boolean hasPendingTune);
 
     int getDeliverySystemType();
-    default int[] getDeliverySystemTypes() {
-      int[] deliverySystemTypes = {DELIVERY_SYSTEM_UNDEFINED};
-      return deliverySystemTypes;
-    };
 
     int readTsStream(byte[] javaBuffer, int javaBufferSize);
 
@@ -96,7 +84,7 @@
     public @interface FilterType {}
 
     /** Modulation Type */
-    @StringDef({MODULATION_8VSB, MODULATION_QAM256, MODULATION_QAM16, MODULATION_QAM64})
+    @StringDef({MODULATION_8VSB, MODULATION_QAM256})
     @Retention(RetentionPolicy.SOURCE)
     public @interface ModulationType {}
 
@@ -120,7 +108,6 @@
 
     /** Built in tuner type */
     @IntDef({
-        BUILT_IN_TUNER_TYPE_ARCHER,
         BUILT_IN_TUNER_TYPE_LINUX_DVB
     })
     @Retention(RetentionPolicy.SOURCE)
diff --git a/tuner/src/com/android/tv/tuner/dvb/DvbTunerHalFactory.java b/tuner/src/com/android/tv/tuner/builtin/BuiltInTunerHalFactory.java
similarity index 60%
rename from tuner/src/com/android/tv/tuner/dvb/DvbTunerHalFactory.java
rename to tuner/src/com/android/tv/tuner/builtin/BuiltInTunerHalFactory.java
index 24d7e1f..9a0be74 100644
--- a/tuner/src/com/android/tv/tuner/dvb/DvbTunerHalFactory.java
+++ b/tuner/src/com/android/tv/tuner/builtin/BuiltInTunerHalFactory.java
@@ -14,29 +14,39 @@
  * limitations under the License.
  */
 
-package com.android.tv.tuner.dvb;
+package com.android.tv.tuner.builtin;
 
 import android.content.Context;
 import android.support.annotation.WorkerThread;
 import android.util.Log;
 import android.util.Pair;
-
+import com.android.tv.common.customization.CustomizationManager;
+import com.android.tv.common.feature.Model;
+import com.android.tv.tuner.DvbTunerHal;
 import com.android.tv.tuner.api.Tuner;
 import com.android.tv.tuner.api.TunerFactory;
 
+
 /** TunerHal factory that creates all built in tuner types. */
-public final class DvbTunerHalFactory implements TunerFactory {
-    private static final String TAG = "DvbTunerHalFactory";
+public final class BuiltInTunerHalFactory implements TunerFactory {
+    private static final String TAG = "BuiltInTunerHalFactory";
     private static final boolean DEBUG = false;
 
-    private final int mBuiltInTunerType = Tuner.BUILT_IN_TUNER_TYPE_LINUX_DVB;
+    private Integer mBuiltInTunerType;
 
-    public static final TunerFactory INSTANCE = new DvbTunerHalFactory();
+    public static final TunerFactory INSTANCE = new BuiltInTunerHalFactory();
 
-    private DvbTunerHalFactory() {}
+    private BuiltInTunerHalFactory() {}
 
     @Tuner.BuiltInTunerType
     private int getBuiltInTunerType(Context context) {
+        if (mBuiltInTunerType == null) {
+            mBuiltInTunerType = 0;
+            if (CustomizationManager.hasLinuxDvbBuiltInTuner(context)
+                    && DvbTunerHal.getNumberOfDevices(context) > 0) {
+                mBuiltInTunerType = Tuner.BUILT_IN_TUNER_TYPE_LINUX_DVB;
+            }
+        }
         return mBuiltInTunerType;
     }
 
@@ -70,6 +80,17 @@
     @Override
     @WorkerThread
     public Pair<Integer, Integer> getTunerTypeAndCount(Context context) {
-        return Pair.create(Tuner.TUNER_TYPE_BUILT_IN, DvbTunerHal.getNumberOfDevices(context));
+        if (useBuiltInTuner(context)) {
+            if (getBuiltInTunerType(context) == Tuner.BUILT_IN_TUNER_TYPE_LINUX_DVB) {
+                return new Pair<>(
+                        Tuner.TUNER_TYPE_BUILT_IN, DvbTunerHal.getNumberOfDevices(context));
+            }
+        } else {
+            int usbTunerCount = DvbTunerHal.getNumberOfDevices(context);
+            if (usbTunerCount > 0) {
+                return new Pair<>(Tuner.TUNER_TYPE_USB, usbTunerCount);
+            }
+        }
+        return new Pair<>(null, 0);
     }
 }
diff --git a/tuner/src/com/android/tv/tuner/cc/CaptionLayout.java b/tuner/src/com/android/tv/tuner/cc/CaptionLayout.java
index 62a4e15..eb9ad46 100644
--- a/tuner/src/com/android/tv/tuner/cc/CaptionLayout.java
+++ b/tuner/src/com/android/tv/tuner/cc/CaptionLayout.java
@@ -18,7 +18,7 @@
 
 import android.content.Context;
 import android.util.AttributeSet;
-import com.android.tv.tuner.data.Track.AtscCaptionTrack;
+import com.android.tv.tuner.data.nano.Track.AtscCaptionTrack;
 import com.android.tv.tuner.layout.ScaledLayout;
 
 /**
diff --git a/tuner/src/com/android/tv/tuner/cc/CaptionTrackRenderer.java b/tuner/src/com/android/tv/tuner/cc/CaptionTrackRenderer.java
index 75776d6..4a1c7c1 100644
--- a/tuner/src/com/android/tv/tuner/cc/CaptionTrackRenderer.java
+++ b/tuner/src/com/android/tv/tuner/cc/CaptionTrackRenderer.java
@@ -27,7 +27,7 @@
 import com.android.tv.tuner.data.Cea708Data.CaptionWindow;
 import com.android.tv.tuner.data.Cea708Data.CaptionWindowAttr;
 import com.android.tv.tuner.data.Cea708Parser;
-import com.android.tv.tuner.data.Track.AtscCaptionTrack;
+import com.android.tv.tuner.data.nano.Track.AtscCaptionTrack;
 import java.util.ArrayList;
 
 /** Decodes and renders CEA-708. */
@@ -89,7 +89,7 @@
             return;
         }
         if (DEBUG) {
-            Log.d(TAG, "Start captionTrack " + captionTrack.getLanguage());
+            Log.d(TAG, "Start captionTrack " + captionTrack.language);
         }
         reset();
         mCaptionLayout.setCaptionTrack(captionTrack);
diff --git a/tuner/src/com/android/tv/tuner/cc/CaptionWindowLayout.java b/tuner/src/com/android/tv/tuner/cc/CaptionWindowLayout.java
index 8c699d5..13c6ff4 100644
--- a/tuner/src/com/android/tv/tuner/cc/CaptionWindowLayout.java
+++ b/tuner/src/com/android/tv/tuner/cc/CaptionWindowLayout.java
@@ -459,14 +459,14 @@
     private boolean isKoreanLanguageTrack() {
         return mCaptionLayout != null
                 && mCaptionLayout.getCaptionTrack() != null
-                && mCaptionLayout.getCaptionTrack().hasLanguage()
-                && "KOR".equalsIgnoreCase(mCaptionLayout.getCaptionTrack().getLanguage());
+                && mCaptionLayout.getCaptionTrack().language != null
+                && "KOR".compareToIgnoreCase(mCaptionLayout.getCaptionTrack().language) == 0;
     }
 
     private boolean isWideAspectRatio() {
         return mCaptionLayout != null
                 && mCaptionLayout.getCaptionTrack() != null
-                && mCaptionLayout.getCaptionTrack().getWideAspectRatio();
+                && mCaptionLayout.getCaptionTrack().wideAspectRatio;
     }
 
     private void updateWidestChar() {
diff --git a/tuner/src/com/android/tv/tuner/data/Cea708Parser.java b/tuner/src/com/android/tv/tuner/data/Cea708Parser.java
index 7a5538c..92834b2 100644
--- a/tuner/src/com/android/tv/tuner/data/Cea708Parser.java
+++ b/tuner/src/com/android/tv/tuner/data/Cea708Parser.java
@@ -138,7 +138,6 @@
     private long mLastDiscoveryLaunchedMs = SystemClock.elapsedRealtime();
     private int mCommand = 0;
     private int mListenServiceNumber = 0;
-    private int mDtvCcPacketCalculatedSize = 0;
     private boolean mDtvCcPacking = false;
     private boolean mFirstServiceNumberDiscovered;
 
@@ -230,7 +229,6 @@
         mBuffer.setLength(0);
         mDiscoveredNumBytes.clear();
         mCommand = 0;
-        mDtvCcPacketCalculatedSize = 0;
         mDtvCcPacking = false;
     }
 
@@ -286,33 +284,29 @@
         for (int i = 0; i < ccPacket.ccCount; ++i) {
             boolean ccValid = (bytes[pos] & 0x04) != 0;
             int ccType = bytes[pos] & 0x03;
+
+            // The dtvcc should be considered complete:
+            // - if either ccValid is set and ccType is 3
+            // - or ccValid is clear and ccType is 2 or 3.
             if (ccValid) {
-                // The dtvcc should be considered complete:
-                // if ccType is 3 or if the packet size is reached.
                 if (ccType == CC_TYPE_DTVCC_PACKET_START) {
                     if (mDtvCcPacking) {
                         parseDtvCcPacket(mDtvCcPacket.buffer(), mDtvCcPacket.length());
                         mDtvCcPacket.clear();
-                        mDtvCcPacketCalculatedSize = 0;
                     }
                     mDtvCcPacking = true;
-                    int packetSize = bytes[pos + 1] & 0x3F; // last 6 bits
-                    if (packetSize == 0) {
-                        packetSize = DTVCC_MAX_PACKET_SIZE;
-                    }
-                    mDtvCcPacketCalculatedSize = packetSize * DTVCC_PACKET_SIZE_SCALE_FACTOR;
                     mDtvCcPacket.append(bytes[pos + 1]);
                     mDtvCcPacket.append(bytes[pos + 2]);
                 } else if (mDtvCcPacking && ccType == CC_TYPE_DTVCC_PACKET_DATA) {
                     mDtvCcPacket.append(bytes[pos + 1]);
                     mDtvCcPacket.append(bytes[pos + 2]);
                 }
+            } else {
                 if ((ccType == CC_TYPE_DTVCC_PACKET_START || ccType == CC_TYPE_DTVCC_PACKET_DATA)
-                        && mDtvCcPacking && mDtvCcPacket.length() == mDtvCcPacketCalculatedSize) {
+                        && mDtvCcPacking) {
                     mDtvCcPacking = false;
                     parseDtvCcPacket(mDtvCcPacket.buffer(), mDtvCcPacket.length());
                     mDtvCcPacket.clear();
-                    mDtvCcPacketCalculatedSize = 0;
                 }
             }
             pos += 3;
diff --git a/tuner/src/com/android/tv/tuner/data/PsiData.java b/tuner/src/com/android/tv/tuner/data/PsiData.java
index 74f1603..9b7c2e2 100644
--- a/tuner/src/com/android/tv/tuner/data/PsiData.java
+++ b/tuner/src/com/android/tv/tuner/data/PsiData.java
@@ -16,8 +16,8 @@
 
 package com.android.tv.tuner.data;
 
-import com.android.tv.tuner.data.Track.AtscAudioTrack;
-import com.android.tv.tuner.data.Track.AtscCaptionTrack;
+import com.android.tv.tuner.data.nano.Track.AtscAudioTrack;
+import com.android.tv.tuner.data.nano.Track.AtscCaptionTrack;
 import java.util.List;
 
 /** Collection of MPEG PSI table items. */
diff --git a/tuner/src/com/android/tv/tuner/data/PsipData.java b/tuner/src/com/android/tv/tuner/data/PsipData.java
index 108ce3f..d4af093 100644
--- a/tuner/src/com/android/tv/tuner/data/PsipData.java
+++ b/tuner/src/com/android/tv/tuner/data/PsipData.java
@@ -20,8 +20,8 @@
 import android.text.TextUtils;
 import android.text.format.DateUtils;
 import com.android.tv.common.util.StringUtils;
-import com.android.tv.tuner.data.Track.AtscAudioTrack;
-import com.android.tv.tuner.data.Track.AtscCaptionTrack;
+import com.android.tv.tuner.data.nano.Track.AtscAudioTrack;
+import com.android.tv.tuner.data.nano.Track.AtscCaptionTrack;
 import com.android.tv.tuner.util.ConvertUtils;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -495,10 +495,10 @@
         public String toString() {
             return String.format(
                     Locale.US,
-                    "AC3 audio stream sampleRateCode: %d, bsid: %d, bitRateCode: %d, surroundMode:"
-                            + " %d, bsmod: %d, numChannels: %d, fullSvc: %s, langCod: %d, langCod2:"
-                            + " %d, mainId: %d, priority: %d, avcflags: %d, text: %s, language: %s,"
-                            + " language2: %s",
+                    "AC3 audio stream sampleRateCode: %d, bsid: %d, bitRateCode: %d, "
+                            + "surroundMode: %d, bsmod: %d, numChannels: %d, fullSvc: %s, langCod: %d, "
+                            + "langCod2: %d, mainId: %d, priority: %d, avcflags: %d, text: %s, language: %s"
+                            + ", language2: %s",
                     mSampleRateCode,
                     mBsid,
                     mBitRateCode,
@@ -832,7 +832,7 @@
             }
             ArrayList<String> languages = new ArrayList<>();
             for (AtscAudioTrack audioTrack : mAudioTracks) {
-                languages.add(audioTrack.getLanguage());
+                languages.add(audioTrack.language);
             }
             return TextUtils.join(",", languages);
         }
diff --git a/tuner/src/com/android/tv/tuner/data/SectionParser.java b/tuner/src/com/android/tv/tuner/data/SectionParser.java
index 3c16749..d3dba6b 100644
--- a/tuner/src/com/android/tv/tuner/data/SectionParser.java
+++ b/tuner/src/com/android/tv/tuner/data/SectionParser.java
@@ -24,8 +24,7 @@
 import android.util.ArraySet;
 import android.util.Log;
 import android.util.SparseArray;
-import com.android.tv.common.feature.Model;
-import com.android.tv.tuner.data.Channel.AtscServiceType;
+
 import com.android.tv.tuner.data.PsiData.PatItem;
 import com.android.tv.tuner.data.PsiData.PmtItem;
 import com.android.tv.tuner.data.PsipData.Ac3AudioDescriptor;
@@ -46,8 +45,9 @@
 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.Track.AtscAudioTrack;
-import com.android.tv.tuner.data.Track.AtscCaptionTrack;
+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 java.io.UnsupportedEncodingException;
@@ -105,7 +105,7 @@
     private static final int RATING_REGION_US_TV = 1;
     private static final int RATING_REGION_KR_TV = 4;
 
-    // The following values are defined in the TV app.
+    // 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";
@@ -916,8 +916,8 @@
                 Log.d(
                         TAG,
                         String.format(
-                                "Found channel [%s] %s - serviceType: %d tsid: 0x%x program: %d"
-                                    + " channel: %d-%d encrypted: %b hidden: %b, descriptors: %d",
+                                "Found channel [%s] %s - serviceType: %d tsid: 0x%x program: %d "
+                                        + "channel: %d-%d encrypted: %b hidden: %b, descriptors: %d",
                                 shortName,
                                 longName,
                                 serviceType,
@@ -929,14 +929,14 @@
                                 hidden,
                                 descriptors.size()));
             }
-            if ((serviceType == AtscServiceType.SERVICE_TYPE_ATSC_AUDIO_VALUE
+            if (!accessControlled
+                    && !hidden
+                    && (serviceType == Channel.AtscServiceType.SERVICE_TYPE_ATSC_AUDIO
                             || serviceType
-                                    == AtscServiceType.SERVICE_TYPE_ATSC_DIGITAL_TELEVISION_VALUE
+                                    == Channel.AtscServiceType.SERVICE_TYPE_ATSC_DIGITAL_TELEVISION
                             || serviceType
-                                    == AtscServiceType
-                                            .SERVICE_TYPE_UNASSOCIATED_SMALL_SCREEN_SERVICE_VALUE)
-                    && !accessControlled
-                    && !hidden) {
+                                    == Channel.AtscServiceType
+                                            .SERVICE_TYPE_UNASSOCIATED_SMALL_SCREEN_SERVICE)) {
                 // Hide hidden, encrypted, or unsupported ATSC service type channels
                 results.add(
                         new VctItem(
@@ -1212,20 +1212,16 @@
         for (TsDescriptor descriptor : descriptors) {
             if (descriptor instanceof Ac3AudioDescriptor) {
                 Ac3AudioDescriptor audioDescriptor = (Ac3AudioDescriptor) descriptor;
-                String language = null;
+                AtscAudioTrack audioTrack = new AtscAudioTrack();
                 if (audioDescriptor.getLanguage() != null) {
-                    language = audioDescriptor.getLanguage();
+                    audioTrack.language = audioDescriptor.getLanguage();
                 }
-                if (language == null) {
-                    language = "";
+                if (audioTrack.language == null) {
+                    audioTrack.language = "";
                 }
-                AtscAudioTrack audioTrack =
-                        AtscAudioTrack.newBuilder()
-                                .setLanguage(language)
-                                .setAudioType(AtscAudioTrack.AudioType.AUDIOTYPE_UNDEFINED)
-                                .setChannelCount(audioDescriptor.getNumChannels())
-                                .setSampleRate(audioDescriptor.getSampleRate())
-                                .build();
+                audioTrack.audioType = AtscAudioTrack.AudioType.AUDIOTYPE_UNDEFINED;
+                audioTrack.channelCount = audioDescriptor.getNumChannels();
+                audioTrack.sampleRate = audioDescriptor.getSampleRate();
                 ac3Tracks.add(audioTrack);
             }
         }
@@ -1258,27 +1254,26 @@
         }
         int size = Math.max(ac3Tracks.size(), iso639LanguageTracks.size());
         for (int i = 0; i < size; ++i) {
-            AtscAudioTrack.Builder audioTrack = null;
+            AtscAudioTrack audioTrack = null;
             if (i < ac3Tracks.size()) {
-                audioTrack = ac3Tracks.get(i).toBuilder();
+                audioTrack = ac3Tracks.get(i);
             }
             if (i < iso639LanguageTracks.size()) {
                 if (audioTrack == null) {
-                    audioTrack = iso639LanguageTracks.get(i).toBuilder();
+                    audioTrack = iso639LanguageTracks.get(i);
                 } else {
                     AtscAudioTrack iso639LanguageTrack = iso639LanguageTracks.get(i);
-                    if (!audioTrack.hasLanguage()
-                            || TextUtils.equals(audioTrack.getLanguage(), "")) {
-                        audioTrack.setLanguage(iso639LanguageTrack.getLanguage());
+                    if (audioTrack.language == null || TextUtils.equals(audioTrack.language, "")) {
+                        audioTrack.language = iso639LanguageTrack.language;
                     }
-                    audioTrack.setAudioType(iso639LanguageTrack.getAudioType());
+                    audioTrack.audioType = iso639LanguageTrack.audioType;
                 }
             }
-            String language = ISO_LANGUAGE_CODE_MAP.get(audioTrack.getLanguage());
+            String language = ISO_LANGUAGE_CODE_MAP.get(audioTrack.language);
             if (language != null) {
-                audioTrack = audioTrack.setLanguage(language);
+                audioTrack.language = language;
             }
-            tracks.add(audioTrack.build());
+            tracks.add(audioTrack);
         }
         return tracks;
     }
@@ -1597,16 +1592,10 @@
                 return null;
             }
             String language = new String(data, pos, 3);
-            int audioTypeInt = data[pos + 3] & 0xff;
-            AtscAudioTrack.AudioType audioType = AtscAudioTrack.AudioType.forNumber(audioTypeInt);
-            if (audioType == null) {
-                audioType = AtscAudioTrack.AudioType.AUDIOTYPE_UNDEFINED;
-            }
-            AtscAudioTrack audioTrack =
-                    AtscAudioTrack.newBuilder()
-                            .setLanguage(language)
-                            .setAudioType(audioType)
-                            .build();
+            int audioType = data[pos + 3] & 0xff;
+            AtscAudioTrack audioTrack = new AtscAudioTrack();
+            audioTrack.language = language;
+            audioTrack.audioType = audioType;
             audioTracks.add(audioTrack);
             pos += 4;
         }
@@ -1645,13 +1634,11 @@
             reserved[0] |= (byte) ((data[pos + 1] & 0xc0) >>> 6);
             reserved[1] = (byte) ((data[pos + 1] & 0x3f) << 2);
             pos += 2;
-            AtscCaptionTrack captionTrack =
-                    AtscCaptionTrack.newBuilder()
-                            .setLanguage(language)
-                            .setServiceNumber(captionServiceNumber)
-                            .setEasyReader(easyReader)
-                            .setWideAspectRatio(wideAspectRatio)
-                            .build();
+            AtscCaptionTrack captionTrack = new AtscCaptionTrack();
+            captionTrack.language = language;
+            captionTrack.serviceNumber = captionServiceNumber;
+            captionTrack.easyReader = easyReader;
+            captionTrack.wideAspectRatio = wideAspectRatio;
             services.add(captionTrack);
         }
         return new CaptionServiceDescriptor(services);
@@ -2088,11 +2075,6 @@
     }
 
     private static boolean checkSanity(byte[] data) {
-        // Skipping CRC checking on Archer since TS data here was modified without updating CRC
-        // value. For details, see b/28616908.
-        if (Model.ARCHER.isEnabled()) {
-            return true;
-        }
         if (data.length <= 1) {
             return false;
         }
diff --git a/tuner/src/com/android/tv/tuner/data/TunerChannel.java b/tuner/src/com/android/tv/tuner/data/TunerChannel.java
index 5872cd5..d20c343 100644
--- a/tuner/src/com/android/tv/tuner/data/TunerChannel.java
+++ b/tuner/src/com/android/tv/tuner/data/TunerChannel.java
@@ -20,10 +20,12 @@
 import android.support.annotation.NonNull;
 import android.util.Log;
 import com.android.tv.common.util.StringUtils;
-import com.android.tv.tuner.data.Channel.DeliverySystemType;
-import com.android.tv.tuner.data.Channel.TunerChannelProto;
-import com.android.tv.tuner.data.Track.AtscAudioTrack;
-import com.android.tv.tuner.data.Track.AtscCaptionTrack;
+import com.android.tv.tuner.data.nano.Channel;
+import com.android.tv.tuner.data.nano.Channel.TunerChannelProto;
+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.google.protobuf.nano.MessageNano;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -53,7 +55,7 @@
                 "Extended Parameterized Service"
             };
     private static final String ATSC_SERVICE_TYPE_NAME_RESERVED =
-            ATSC_SERVICE_TYPE_NAMES[Channel.AtscServiceType.SERVICE_TYPE_ATSC_RESERVED_VALUE];
+            ATSC_SERVICE_TYPE_NAMES[Channel.AtscServiceType.SERVICE_TYPE_ATSC_RESERVED];
 
     public static final int INVALID_FREQUENCY = -1;
 
@@ -64,128 +66,93 @@
     public static final int INVALID_STREAMTYPE = -1;
 
     // @GuardedBy(this) Writing operations and toByteArray will be guarded. b/34197766
-    private TunerChannelProto mProto;
+    private final TunerChannelProto mProto;
 
     private TunerChannel(
-            PsipData.VctItem channel,
-            int programNumber,
-            List<PsiData.PmtItem> pmtItems,
-            Channel.TunerType type) {
-        String shortName = "";
-        String longName = "";
-        String description = "";
-        int tsid = 0;
-        int virtualMajor = 0;
-        int virtualMinor = 0;
-        Channel.AtscServiceType serviceType =
-                Channel.AtscServiceType.SERVICE_TYPE_ATSC_DIGITAL_TELEVISION;
-        if (channel != null) {
-            shortName = channel.getShortName();
-            tsid = channel.getChannelTsid();
-            programNumber = channel.getProgramNumber();
-            virtualMajor = channel.getMajorChannelNumber();
-            virtualMinor = channel.getMinorChannelNumber();
-            Channel.AtscServiceType chanServiceType =
-                    Channel.AtscServiceType.forNumber(channel.getServiceType());
-            if (chanServiceType != null) {
-                serviceType = chanServiceType;
+            PsipData.VctItem channel, int programNumber, List<PsiData.PmtItem> pmtItems, int type) {
+        mProto = new TunerChannelProto();
+        if (channel == null) {
+            mProto.shortName = "";
+            mProto.tsid = 0;
+            mProto.programNumber = programNumber;
+            mProto.virtualMajor = 0;
+            mProto.virtualMinor = 0;
+        } else {
+            mProto.shortName = channel.getShortName();
+            if (channel.getLongName() != null) {
+                mProto.longName = channel.getLongName();
             }
-            longName = (channel.getLongName() != null ? channel.getLongName() : longName);
-            description =
-                    (channel.getDescription() != null ? channel.getDescription() : description);
+            mProto.tsid = channel.getChannelTsid();
+            mProto.programNumber = channel.getProgramNumber();
+            mProto.virtualMajor = channel.getMajorChannelNumber();
+            mProto.virtualMinor = channel.getMinorChannelNumber();
+            if (channel.getDescription() != null) {
+                mProto.description = channel.getDescription();
+            }
+            mProto.serviceType = channel.getServiceType();
         }
-        TunerChannelProto tunerChannelProto =
-                TunerChannelProto.newBuilder()
-                        .setShortName(shortName)
-                        .setTsid(tsid)
-                        .setProgramNumber(programNumber)
-                        .setVirtualMajor(virtualMajor)
-                        .setVirtualMinor(virtualMinor)
-                        .setServiceType(serviceType)
-                        .setLongName(longName)
-                        .setDescription(description)
-                        .build();
-        initProto(pmtItems, type, tunerChannelProto);
+        initProto(pmtItems, type);
     }
 
-    private void initProto(
-            List<PsiData.PmtItem> pmtItems,
-            Channel.TunerType type,
-            TunerChannelProto tunerChannelProto) {
-        int videoPid = INVALID_PID;
-        int pcrPid = 0;
-        Channel.VideoStreamType videoStreamType = Channel.VideoStreamType.UNSET;
+    private void initProto(List<PsiData.PmtItem> pmtItems, int type) {
+        mProto.type = type;
+        mProto.channelId = -1L;
+        mProto.frequency = INVALID_FREQUENCY;
+        mProto.videoPid = INVALID_PID;
+        mProto.videoStreamType = INVALID_STREAMTYPE;
         List<Integer> audioPids = new ArrayList<>();
-        List<Channel.AudioStreamType> audioStreamTypes = new ArrayList<>();
+        List<Integer> audioStreamTypes = new ArrayList<>();
         for (PsiData.PmtItem pmt : pmtItems) {
             switch (pmt.getStreamType()) {
                     // MPEG ES stream video types
-                case Channel.VideoStreamType.MPEG1_VALUE:
-                case Channel.VideoStreamType.MPEG2_VALUE:
-                case Channel.VideoStreamType.H263_VALUE:
-                case Channel.VideoStreamType.H264_VALUE:
-                case Channel.VideoStreamType.H265_VALUE:
-                    videoPid = pmt.getEsPid();
-                    videoStreamType = Channel.VideoStreamType.forNumber(pmt.getStreamType());
+                case Channel.VideoStreamType.MPEG1:
+                case Channel.VideoStreamType.MPEG2:
+                case Channel.VideoStreamType.H263:
+                case Channel.VideoStreamType.H264:
+                case Channel.VideoStreamType.H265:
+                    mProto.videoPid = pmt.getEsPid();
+                    mProto.videoStreamType = pmt.getStreamType();
                     break;
 
                     // MPEG ES stream audio types
-                case Channel.AudioStreamType.MPEG1AUDIO_VALUE:
-                case Channel.AudioStreamType.MPEG2AUDIO_VALUE:
-                case Channel.AudioStreamType.MPEG2AACAUDIO_VALUE:
-                case Channel.AudioStreamType.MPEG4LATMAACAUDIO_VALUE:
-                case Channel.AudioStreamType.A52AC3AUDIO_VALUE:
-                case Channel.AudioStreamType.EAC3AUDIO_VALUE:
+                case Channel.AudioStreamType.MPEG1AUDIO:
+                case Channel.AudioStreamType.MPEG2AUDIO:
+                case Channel.AudioStreamType.MPEG2AACAUDIO:
+                case Channel.AudioStreamType.MPEG4LATMAACAUDIO:
+                case Channel.AudioStreamType.A52AC3AUDIO:
+                case Channel.AudioStreamType.EAC3AUDIO:
                     audioPids.add(pmt.getEsPid());
-                    audioStreamTypes.add(Channel.AudioStreamType.forNumber(pmt.getStreamType()));
+                    audioStreamTypes.add(pmt.getStreamType());
                     break;
 
                     // Non MPEG ES stream types
                 case 0x100: // PmtItem.ES_PID_PCR:
-                    pcrPid = pmt.getEsPid();
+                    mProto.pcrPid = pmt.getEsPid();
                     break;
                 default:
                     // fall out
             }
         }
-        mProto =
-                TunerChannelProto.newBuilder(tunerChannelProto)
-                        .setType(type)
-                        .setChannelId(-1L)
-                        .setFrequency(INVALID_FREQUENCY)
-                        .setVideoPid(videoPid)
-                        .setVideoStreamType(videoStreamType)
-                        .addAllAudioPids(audioPids)
-                        .setAudioTrackIndex(audioPids.isEmpty() ? -1 : 0)
-                        .addAllAudioStreamTypes(audioStreamTypes)
-                        .setPcrPid(pcrPid)
-                        .build();
+        mProto.audioPids = Ints.toArray(audioPids);
+        mProto.audioStreamTypes = Ints.toArray(audioStreamTypes);
+        mProto.audioTrackIndex = (audioPids.size() > 0) ? 0 : -1;
     }
 
     private TunerChannel(
-            int programNumber,
-            Channel.TunerType type,
-            PsipData.SdtItem channel,
-            List<PsiData.PmtItem> pmtItems) {
-        String shortName = "";
-        Channel.AtscServiceType serviceType =
-                Channel.AtscServiceType.SERVICE_TYPE_ATSC_DIGITAL_TELEVISION;
-        if (channel != null) {
-            shortName = channel.getServiceName();
-            programNumber = channel.getServiceId();
-            Channel.AtscServiceType chanServiceType =
-                    Channel.AtscServiceType.forNumber(channel.getServiceType());
-            if (chanServiceType != null) {
-                serviceType = chanServiceType;
-            }
+            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();
         }
-        TunerChannelProto tunerChannelProto =
-                TunerChannelProto.newBuilder()
-                        .setShortName(shortName)
-                        .setProgramNumber(programNumber)
-                        .setServiceType(serviceType)
-                        .build();
-        initProto(pmtItems, type, tunerChannelProto);
+        initProto(pmtItems, type);
     }
 
     /** Initialize tuner channel with VCT items and PMT items. */
@@ -266,23 +233,23 @@
     }
 
     public String getName() {
-        return !mProto.getShortName().isEmpty() ? mProto.getShortName() : mProto.getLongName();
+        return (!mProto.shortName.isEmpty()) ? mProto.shortName : mProto.longName;
     }
 
     public String getShortName() {
-        return mProto.getShortName();
+        return mProto.shortName;
     }
 
     public int getProgramNumber() {
-        return mProto.getProgramNumber();
+        return mProto.programNumber;
     }
 
     public int getServiceType() {
-        return mProto.getServiceType().getNumber();
+        return mProto.serviceType;
     }
 
     public String getServiceTypeName() {
-        int serviceType = getServiceType();
+        int serviceType = mProto.serviceType;
         if (serviceType >= 0 && serviceType < ATSC_SERVICE_TYPE_NAMES.length) {
             return ATSC_SERVICE_TYPE_NAMES[serviceType];
         }
@@ -290,129 +257,105 @@
     }
 
     public int getVirtualMajor() {
-        return mProto.getVirtualMajor();
+        return mProto.virtualMajor;
     }
 
     public int getVirtualMinor() {
-        return mProto.getVirtualMinor();
-    }
-
-    public DeliverySystemType getDeliverySystemType() {
-        return mProto.getDeliverySystemType();
+        return mProto.virtualMinor;
     }
 
     public int getFrequency() {
-        return mProto.getFrequency();
+        return mProto.frequency;
     }
 
     public String getModulation() {
-        return mProto.getModulation();
+        return mProto.modulation;
     }
 
     public int getTsid() {
-        return mProto.getTsid();
+        return mProto.tsid;
     }
 
     public int getVideoPid() {
-        return mProto.getVideoPid();
+        return mProto.videoPid;
     }
 
     public synchronized void setVideoPid(int videoPid) {
-        mProto = mProto.toBuilder().setVideoPid(videoPid).build();
+        mProto.videoPid = videoPid;
     }
 
     public int getVideoStreamType() {
-        return mProto.getVideoStreamType().getNumber();
+        return mProto.videoStreamType;
     }
 
     public int getAudioPid() {
-        if (!mProto.hasAudioTrackIndex() || mProto.getAudioTrackIndex() == -1) {
+        if (mProto.audioTrackIndex == -1) {
             return INVALID_PID;
         }
-        return mProto.getAudioPids(mProto.getAudioTrackIndex());
+        return mProto.audioPids[mProto.audioTrackIndex];
     }
 
     public int getAudioStreamType() {
-        if (!mProto.hasAudioTrackIndex() || mProto.getAudioTrackIndex() == -1) {
+        if (mProto.audioTrackIndex == -1) {
             return INVALID_STREAMTYPE;
         }
-        return mProto.getAudioStreamTypes(mProto.getAudioTrackIndex()).getNumber();
+        return mProto.audioStreamTypes[mProto.audioTrackIndex];
     }
 
     public List<Integer> getAudioPids() {
-        return mProto.getAudioPidsList();
+        return Ints.asList(mProto.audioPids);
     }
 
     public synchronized void setAudioPids(List<Integer> audioPids) {
-        mProto = mProto.toBuilder().clearAudioPids().addAllAudioPids(audioPids).build();
+        mProto.audioPids = Ints.toArray(audioPids);
     }
 
     public List<Integer> getAudioStreamTypes() {
-        List<Channel.AudioStreamType> audioStreamTypes = mProto.getAudioStreamTypesList();
-        List<Integer> audioStreamTypesValues = new ArrayList<>(audioStreamTypes.size());
-
-        for (Channel.AudioStreamType audioStreamType : audioStreamTypes) {
-            audioStreamTypesValues.add(audioStreamType.getNumber());
-        }
-        return audioStreamTypesValues;
+        return Ints.asList(mProto.audioStreamTypes);
     }
 
-    public synchronized void setAudioStreamTypes(List<Integer> audioStreamTypesValues) {
-        List<Channel.AudioStreamType> audioStreamTypes =
-                new ArrayList<>(audioStreamTypesValues.size());
-
-        for (Integer audioStreamTypesValue : audioStreamTypesValues) {
-            audioStreamTypes.add(Channel.AudioStreamType.forNumber(audioStreamTypesValue));
-        }
-        mProto =
-                mProto.toBuilder()
-                        .clearAudioStreamTypes()
-                        .addAllAudioStreamTypes(audioStreamTypes)
-                        .build();
+    public synchronized void setAudioStreamTypes(List<Integer> audioStreamTypes) {
+        mProto.audioStreamTypes = Ints.toArray(audioStreamTypes);
     }
 
     public int getPcrPid() {
-        return mProto.getPcrPid();
+        return mProto.pcrPid;
     }
 
-    public Channel.TunerType getType() {
-        return mProto.getType();
+    public int getType() {
+        return mProto.type;
     }
 
     public synchronized void setFilepath(String filepath) {
-        mProto = mProto.toBuilder().setFilepath(filepath == null ? "" : filepath).build();
+        mProto.filepath = filepath == null ? "" : filepath;
     }
 
     public String getFilepath() {
-        return mProto.getFilepath();
+        return mProto.filepath;
     }
 
     public synchronized void setVirtualMajor(int virtualMajor) {
-        mProto = mProto.toBuilder().setVirtualMajor(virtualMajor).build();
+        mProto.virtualMajor = virtualMajor;
     }
 
     public synchronized void setVirtualMinor(int virtualMinor) {
-        mProto = mProto.toBuilder().setVirtualMinor(virtualMinor).build();
+        mProto.virtualMinor = virtualMinor;
     }
 
     public synchronized void setShortName(String shortName) {
-        mProto = mProto.toBuilder().setShortName(shortName == null ? "" : shortName).build();
-    }
-
-    public synchronized void setDeliverySystemType(DeliverySystemType deliverySystemType) {
-        mProto = mProto.toBuilder().setDeliverySystemType(deliverySystemType).build();
+        mProto.shortName = shortName == null ? "" : shortName;
     }
 
     public synchronized void setFrequency(int frequency) {
-        mProto = mProto.toBuilder().setFrequency(frequency).build();
+        mProto.frequency = frequency;
     }
 
     public synchronized void setModulation(String modulation) {
-        mProto = mProto.toBuilder().setModulation(modulation == null ? "" : modulation).build();
+        mProto.modulation = modulation == null ? "" : modulation;
     }
 
     public boolean hasVideo() {
-        return mProto.hasVideoPid() && mProto.getVideoPid() != INVALID_PID;
+        return mProto.videoPid != INVALID_PID;
     }
 
     public boolean hasAudio() {
@@ -420,11 +363,11 @@
     }
 
     public long getChannelId() {
-        return mProto.getChannelId();
+        return mProto.channelId;
     }
 
     public synchronized void setChannelId(long channelId) {
-        mProto = mProto.toBuilder().setChannelId(channelId).build();
+        mProto.channelId = channelId;
     }
 
     /**
@@ -436,11 +379,11 @@
      *     href="https://developer.android.com/reference/android/media/tv/TvContract.Channels.html#COLUMN_LOCKED">link</a>
      */
     public boolean isLocked() {
-        return mProto.getLocked();
+        return mProto.locked;
     }
 
     public synchronized void setLocked(boolean locked) {
-        mProto = mProto.toBuilder().setLocked(locked).build();
+        mProto.locked = locked;
     }
 
     public String getDisplayNumber() {
@@ -448,91 +391,92 @@
     }
 
     public String getDisplayNumber(boolean ignoreZeroMinorNumber) {
-        if (getVirtualMajor() != 0 && (getVirtualMinor() != 0 || !ignoreZeroMinorNumber)) {
+        if (mProto.virtualMajor != 0 && (mProto.virtualMinor != 0 || !ignoreZeroMinorNumber)) {
             return String.format(
-                    "%d%c%d", getVirtualMajor(), CHANNEL_NUMBER_SEPARATOR, getVirtualMinor());
-        } else if (getVirtualMajor() != 0) {
-            return Integer.toString(getVirtualMajor());
+                    "%d%c%d", mProto.virtualMajor, CHANNEL_NUMBER_SEPARATOR, mProto.virtualMinor);
+        } else if (mProto.virtualMajor != 0) {
+            return Integer.toString(mProto.virtualMajor);
         } else {
-            return Integer.toString(getProgramNumber());
+            return Integer.toString(mProto.programNumber);
         }
     }
 
     public String getDescription() {
-        return mProto.getDescription();
+        return mProto.description;
     }
 
     @Override
     public synchronized void setHasCaptionTrack() {
-        mProto = mProto.toBuilder().setHasCaptionTrack(true).build();
+        mProto.hasCaptionTrack = true;
     }
 
     @Override
     public boolean hasCaptionTrack() {
-        return mProto.getHasCaptionTrack();
+        return mProto.hasCaptionTrack;
     }
 
     @Override
     public List<AtscAudioTrack> getAudioTracks() {
-        return mProto.getAudioTracksList();
+        return Collections.unmodifiableList(Arrays.asList(mProto.audioTracks));
     }
 
     public synchronized void setAudioTracks(List<AtscAudioTrack> audioTracks) {
-        mProto = mProto.toBuilder().clearAudioTracks().addAllAudioTracks(audioTracks).build();
+        mProto.audioTracks = audioTracks.toArray(new AtscAudioTrack[audioTracks.size()]);
     }
 
     @Override
     public List<AtscCaptionTrack> getCaptionTracks() {
-        return mProto.getCaptionTracksList();
+        return Collections.unmodifiableList(Arrays.asList(mProto.captionTracks));
     }
 
     public synchronized void setCaptionTracks(List<AtscCaptionTrack> captionTracks) {
-        mProto = mProto.toBuilder().clearCaptionTracks().addAllCaptionTracks(captionTracks).build();
+        mProto.captionTracks = captionTracks.toArray(new AtscCaptionTrack[captionTracks.size()]);
     }
 
     public synchronized void selectAudioTrack(int index) {
-        if (index < 0 || index >= mProto.getAudioPidsCount()) {
-            index = -1;
+        if (0 <= index && index < mProto.audioPids.length) {
+            mProto.audioTrackIndex = index;
+        } else {
+            mProto.audioTrackIndex = -1;
         }
-        mProto = mProto.toBuilder().setAudioTrackIndex(index).build();
     }
 
     public synchronized void setRecordingProhibited(boolean recordingProhibited) {
-        mProto = mProto.toBuilder().setRecordingProhibited(recordingProhibited).build();
+        mProto.recordingProhibited = recordingProhibited;
     }
 
     public boolean isRecordingProhibited() {
-        return mProto.getRecordingProhibited();
+        return mProto.recordingProhibited;
     }
 
     public synchronized void setVideoFormat(String videoFormat) {
-        mProto = mProto.toBuilder().setVideoFormat(videoFormat == null ? "" : videoFormat).build();
+        mProto.videoFormat = videoFormat == null ? "" : videoFormat;
     }
 
     public String getVideoFormat() {
-        return mProto.getVideoFormat();
+        return mProto.videoFormat;
     }
 
     @Override
     public String toString() {
-        switch (getType()) {
-            case TYPE_FILE:
+        switch (mProto.type) {
+            case Channel.TunerType.TYPE_FILE:
                 return String.format(
                         "{%d-%d %s} Filepath: %s, ProgramNumber %d",
-                        getVirtualMajor(),
-                        getVirtualMinor(),
-                        getShortName(),
-                        getFilepath(),
-                        getProgramNumber());
+                        mProto.virtualMajor,
+                        mProto.virtualMinor,
+                        mProto.shortName,
+                        mProto.filepath,
+                        mProto.programNumber);
                 // case Channel.TunerType.TYPE_TUNER:
             default:
                 return String.format(
                         "{%d-%d %s} Frequency: %d, ProgramNumber %d",
-                        getVirtualMajor(),
-                        getVirtualMinor(),
-                        getShortName(),
-                        getFrequency(),
-                        getProgramNumber());
+                        mProto.virtualMajor,
+                        mProto.virtualMinor,
+                        mProto.shortName,
+                        mProto.frequency,
+                        mProto.programNumber);
         }
     }
 
@@ -551,9 +495,6 @@
         if (ret != 0) {
             return ret;
         }
-        if (getDeliverySystemType() != channel.getDeliverySystemType()) {
-            return 1;
-        }
         // For FileTsStreamer, file paths should be compared.
         return StringUtils.compare(getFilepath(), channel.getFilepath());
     }
@@ -568,21 +509,20 @@
 
     @Override
     public int hashCode() {
-        return Objects.hash(getDeliverySystemType(), getFrequency(), getProgramNumber(), getName(),
-                getFilepath());
+        return Objects.hash(getFrequency(), getProgramNumber(), getName(), getFilepath());
     }
 
     // Serialization
     public synchronized byte[] toByteArray() {
         try {
-            return mProto.toByteArray();
+            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 mProto.toByteArray();
+            return MessageNano.toByteArray(mProto);
         }
     }
 
diff --git a/tuner/src/com/android/tv/tuner/exoplayer/ExoPlayerSampleExtractor.java b/tuner/src/com/android/tv/tuner/exoplayer/ExoPlayerSampleExtractor.java
index 2a22db1..e48cb03 100644
--- a/tuner/src/com/android/tv/tuner/exoplayer/ExoPlayerSampleExtractor.java
+++ b/tuner/src/com/android/tv/tuner/exoplayer/ExoPlayerSampleExtractor.java
@@ -26,32 +26,32 @@
 import android.support.annotation.Nullable;
 import android.support.annotation.VisibleForTesting;
 import android.util.Pair;
-
 import com.android.tv.tuner.exoplayer.audio.MpegTsDefaultAudioTrackRenderer;
 import com.android.tv.tuner.exoplayer.buffer.BufferManager;
 import com.android.tv.tuner.exoplayer.buffer.PlaybackBufferListener;
 import com.android.tv.tuner.exoplayer.buffer.RecordingSampleBuffer;
 import com.android.tv.tuner.exoplayer.buffer.SimpleSampleBuffer;
-
 import com.google.android.exoplayer.MediaFormat;
 import com.google.android.exoplayer.MediaFormatHolder;
 import com.google.android.exoplayer.SampleHolder;
+import com.google.android.exoplayer.upstream.DataSource;
 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.DataSource;
+import com.google.android.exoplayer2.upstream.DataSpec;
 import com.google.android.exoplayer2.upstream.DefaultAllocator;
-import com.google.auto.factory.AutoFactory;
-import com.google.auto.factory.Provided;
-
+import com.google.android.exoplayer2.upstream.TransferListener;
+import com.android.tv.common.flags.ConcurrentDvrPlaybackFlags;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -72,6 +72,7 @@
     private final long mId;
 
     private final Handler.Callback mSourceReaderWorker;
+    private final ConcurrentDvrPlaybackFlags mConcurrentDvrPlaybackFlags;
 
     private BufferManager.SampleBuffer mSampleBuffer;
     private Handler mSourceReaderHandler;
@@ -88,29 +89,13 @@
     private Handler mOnCompletionListenerHandler;
     private IOException mError;
 
-    /**
-     * Factory for {@link ExoPlayerSampleExtractor}.
-     *
-     * <p>This wrapper class keeps other classes from needing to reference the {@link AutoFactory}
-     * generated class.
-     */
-    public interface Factory {
-        public ExoPlayerSampleExtractor create(
-                Uri uri,
-                DataSource source,
-                @Nullable BufferManager bufferManager,
-                PlaybackBufferListener bufferListener,
-                boolean isRecording);
-    }
-
-    @AutoFactory(implementing = Factory.class)
     public ExoPlayerSampleExtractor(
             Uri uri,
-            DataSource source,
-            @Nullable BufferManager bufferManager,
+            final DataSource source,
+            BufferManager bufferManager,
             PlaybackBufferListener bufferListener,
             boolean isRecording,
-            @Provided RecordingSampleBuffer.Factory recordingSampleBufferFactory) {
+            ConcurrentDvrPlaybackFlags concurrentDvrPlaybackFlagsoncurrentDvrPlaybackFlags) {
         this(
                 uri,
                 source,
@@ -119,7 +104,7 @@
                 isRecording,
                 Looper.myLooper(),
                 new HandlerThread("SourceReaderThread"),
-                recordingSampleBufferFactory);
+                concurrentDvrPlaybackFlagsoncurrentDvrPlaybackFlags);
     }
 
     @VisibleForTesting
@@ -132,35 +117,98 @@
             boolean isRecording,
             Looper workerLooper,
             HandlerThread sourceReaderThread,
-            RecordingSampleBuffer.Factory recordingSampleBufferFactory) {
+            ConcurrentDvrPlaybackFlags concurrentDvrPlaybackFlags) {
         // It'll be used as a timeshift file chunk name's prefix.
         mId = System.currentTimeMillis();
+        mConcurrentDvrPlaybackFlags = concurrentDvrPlaybackFlags;
+
+        EventListener eventListener =
+                new EventListener() {
+                    @Override
+                    public void onLoadError(IOException error) {
+                        mError = error;
+                    }
+                };
 
         mSourceReaderThread = sourceReaderThread;
         mSourceReaderWorker =
                 new SourceReaderWorker(
                         new ExtractorMediaSource(
                                 uri,
-                                /* dataSourceFactory= */ () -> source,
+                                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() {
+
+                                            private @Nullable Uri uri;
+
+                                            // TODO: uncomment once this is part of the public API.
+                                            // @Override
+                                            public void addTransferListener(
+                                                    TransferListener transferListener) {
+                                                // Do nothing. Unsupported in V1.
+                                            }
+
+                                            @Override
+                                            public long open(DataSpec dataSpec) throws IOException {
+                                                this.uri = dataSpec.uri;
+                                                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 @Nullable Uri getUri() {
+                                                return uri;
+                                            }
+
+                                            @Override
+                                            public void close() throws IOException {
+                                                source.close();
+                                                uri = null;
+                                            }
+                                        };
+                                    }
+                                },
                                 new ExoPlayerExtractorsFactory(),
                                 new Handler(workerLooper),
-                                /* eventListener= */ error -> mError = error));
+                                eventListener));
         if (isRecording) {
             mSampleBuffer =
-                    recordingSampleBufferFactory.create(
+                    new RecordingSampleBuffer(
                             bufferManager,
                             bufferListener,
                             false,
+                            mConcurrentDvrPlaybackFlags,
                             RecordingSampleBuffer.BUFFER_REASON_RECORDING);
         } else {
             if (bufferManager == null) {
                 mSampleBuffer = new SimpleSampleBuffer(bufferListener);
             } else {
                 mSampleBuffer =
-                        recordingSampleBufferFactory.create(
+                        new RecordingSampleBuffer(
                                 bufferManager,
                                 bufferListener,
                                 true,
+                                mConcurrentDvrPlaybackFlags,
                                 RecordingSampleBuffer.BUFFER_REASON_LIVE_PLAYBACK);
             }
         }
@@ -192,11 +240,15 @@
         public SourceReaderWorker(MediaSource sampleSource) {
             mSampleSource = sampleSource;
             mSampleSourceListener =
-                    (source, timeline, manifest) -> {
-                        // Dynamic stream change is not supported yet. b/28169263
-                        // For now, this will cause EOS and playback reset.
+                    new MediaSource.SourceInfoRefreshListener() {
+                        @Override
+                        public void onSourceInfoRefreshed(
+                                MediaSource source, Timeline timeline, Object manifest) {
+                            // Dynamic stream change is not supported yet. b/28169263
+                            // For now, this will cause EOS and playback reset.
+                        }
                     };
-            mSampleSource.prepareSource(mSampleSourceListener, null);
+            mSampleSource.prepareSource(null, false, mSampleSourceListener, null);
             mDecoderInputBuffer =
                     new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_NORMAL);
             mSampleHolder = new SampleHolder(SampleHolder.BUFFER_REPLACEMENT_MODE_NORMAL);
@@ -313,8 +365,9 @@
                         mMediaPeriod =
                                 mSampleSource.createPeriod(
                                         new MediaSource.MediaPeriodId(0),
-                                        new DefaultAllocator(true, C.DEFAULT_BUFFER_SEGMENT_SIZE),
-                                        0);
+                                        new DefaultAllocator(true, C.DEFAULT_BUFFER_SEGMENT_SIZE)
+// AOSP_Comment_Out                                         , 0
+                                );
                         mMediaPeriod.prepare(this, 0);
                         try {
                             mMediaPeriod.maybeThrowPrepareError();
@@ -433,7 +486,7 @@
                         sample.data.position(0);
                         sample.data.put(mDecoderInputBuffer.data);
                         sample.data.flip();
-                        mPendingSamples.add(Pair.create(index, sample));
+                        mPendingSamples.add(new Pair<>(index, sample));
                         return;
                     }
                     mVideoTrackMet = true;
diff --git a/tuner/src/com/android/tv/tuner/exoplayer/FileSampleExtractor.java b/tuner/src/com/android/tv/tuner/exoplayer/FileSampleExtractor.java
index aaca043..9749e4b 100644
--- a/tuner/src/com/android/tv/tuner/exoplayer/FileSampleExtractor.java
+++ b/tuner/src/com/android/tv/tuner/exoplayer/FileSampleExtractor.java
@@ -17,18 +17,14 @@
 package com.android.tv.tuner.exoplayer;
 
 import android.os.Handler;
-
 import com.android.tv.tuner.exoplayer.buffer.BufferManager;
 import com.android.tv.tuner.exoplayer.buffer.PlaybackBufferListener;
 import com.android.tv.tuner.exoplayer.buffer.RecordingSampleBuffer;
-
 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.auto.factory.AutoFactory;
-import com.google.auto.factory.Provided;
-
+import com.android.tv.common.flags.ConcurrentDvrPlaybackFlags;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
@@ -48,28 +44,16 @@
     private final BufferManager mBufferManager;
     private final PlaybackBufferListener mBufferListener;
     private BufferManager.SampleBuffer mSampleBuffer;
-    private final RecordingSampleBuffer.Factory mRecordingSampleBufferFactory;
+    private final ConcurrentDvrPlaybackFlags mConcurrentDvrPlaybackFlags;
 
-    /**
-     * Factory for {@link FileSampleExtractor}}.
-     *
-     * <p>This wrapper class keeps other classes from needing to reference the {@link AutoFactory}
-     * generated class.
-     */
-    public interface Factory {
-        public FileSampleExtractor create(
-                BufferManager bufferManager, PlaybackBufferListener bufferListener);
-    }
-
-    @AutoFactory(implementing = Factory.class)
     public FileSampleExtractor(
             BufferManager bufferManager,
             PlaybackBufferListener bufferListener,
-            @Provided RecordingSampleBuffer.Factory recordingSampleBufferFactory) {
+            ConcurrentDvrPlaybackFlags concurrentDvrPlaybackFlags) {
         mBufferManager = bufferManager;
         mBufferListener = bufferListener;
+        mConcurrentDvrPlaybackFlags = concurrentDvrPlaybackFlags;
         mTrackCount = -1;
-        mRecordingSampleBufferFactory = recordingSampleBufferFactory;
     }
 
     @Override
@@ -92,10 +76,11 @@
             mTrackFormats.add(MediaFormatUtil.createMediaFormat(trackFormat.format));
         }
         mSampleBuffer =
-                mRecordingSampleBufferFactory.create(
+                new RecordingSampleBuffer(
                         mBufferManager,
                         mBufferListener,
                         true,
+                        mConcurrentDvrPlaybackFlags,
                         RecordingSampleBuffer.BUFFER_REASON_RECORDED_PLAYBACK);
         mSampleBuffer.init(ids, mTrackFormats);
         return true;
diff --git a/tuner/src/com/android/tv/tuner/exoplayer/MpegTsPlayer.java b/tuner/src/com/android/tv/tuner/exoplayer/MpegTsPlayer.java
index 67cf992..6781c61 100644
--- a/tuner/src/com/android/tv/tuner/exoplayer/MpegTsPlayer.java
+++ b/tuner/src/com/android/tv/tuner/exoplayer/MpegTsPlayer.java
@@ -43,8 +43,7 @@
 import com.google.android.exoplayer.TrackRenderer;
 import com.google.android.exoplayer.audio.AudioCapabilities;
 import com.google.android.exoplayer.audio.AudioTrack;
-import com.google.android.exoplayer2.upstream.DataSource;
-
+import com.google.android.exoplayer.upstream.DataSource;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
@@ -148,7 +147,7 @@
      *
      * @param rendererBuilder the builder of track renderers
      * @param handler the handler for the playback events in track renderers
-     * @param sourceManager the manager for {@link TsDataSource}
+     * @param sourceManager the manager for {@link DataSource}
      * @param capabilities the {@link AudioCapabilities} of the current device
      * @param listener the listener for playback state changes
      */
@@ -215,7 +214,7 @@
     }
 
     /**
-     * Creates renderers and {@link TsDataSource} and initializes player.
+     * Creates renderers and {@link DataSource} and initializes player.
      *
      * @param context a {@link Context} instance
      * @param channel to play
diff --git a/tuner/src/com/android/tv/tuner/exoplayer/MpegTsRendererBuilder.java b/tuner/src/com/android/tv/tuner/exoplayer/MpegTsRendererBuilder.java
index f860631..e043907 100644
--- a/tuner/src/com/android/tv/tuner/exoplayer/MpegTsRendererBuilder.java
+++ b/tuner/src/com/android/tv/tuner/exoplayer/MpegTsRendererBuilder.java
@@ -17,51 +17,33 @@
 package com.android.tv.tuner.exoplayer;
 
 import android.content.Context;
-import android.support.annotation.Nullable;
-
 import com.android.tv.tuner.exoplayer.MpegTsPlayer.RendererBuilder;
 import com.android.tv.tuner.exoplayer.MpegTsPlayer.RendererBuilderCallback;
 import com.android.tv.tuner.exoplayer.audio.MpegTsDefaultAudioTrackRenderer;
 import com.android.tv.tuner.exoplayer.buffer.BufferManager;
 import com.android.tv.tuner.exoplayer.buffer.PlaybackBufferListener;
-
 import com.google.android.exoplayer.MediaCodecSelector;
 import com.google.android.exoplayer.SampleSource;
 import com.google.android.exoplayer.TrackRenderer;
-import com.google.android.exoplayer2.upstream.DataSource;
-import com.google.auto.factory.AutoFactory;
-import com.google.auto.factory.Provided;
+import com.google.android.exoplayer.upstream.DataSource;
+import com.android.tv.common.flags.ConcurrentDvrPlaybackFlags;
 
 /** Builder for renderer objects for {@link MpegTsPlayer}. */
 public class MpegTsRendererBuilder implements RendererBuilder {
     private final Context mContext;
     private final BufferManager mBufferManager;
     private final PlaybackBufferListener mBufferListener;
-    private final MpegTsSampleExtractor.Factory mMpegTsSampleExtractorFactory;
+    private final ConcurrentDvrPlaybackFlags mConcurrentDvrPlaybackFlags;
 
-    /**
-     * Factory for {@link MpegTsRendererBuilder}.
-     *
-     * <p>This wrapper class keeps other classes from needing to reference the {@link AutoFactory}
-     * generated class.
-     */
-    public interface Factory {
-        public MpegTsRendererBuilder create(
-                Context context,
-                @Nullable BufferManager bufferManager,
-                PlaybackBufferListener bufferListener);
-    }
-
-    @AutoFactory(implementing = Factory.class)
     public MpegTsRendererBuilder(
             Context context,
-            @Nullable BufferManager bufferManager,
+            BufferManager bufferManager,
             PlaybackBufferListener bufferListener,
-            @Provided MpegTsSampleExtractor.Factory mpegTsSampleExtractorFactory) {
+            ConcurrentDvrPlaybackFlags concurrentDvrPlaybackFlags) {
         mContext = context;
         mBufferManager = bufferManager;
         mBufferListener = bufferListener;
-        mMpegTsSampleExtractorFactory = mpegTsSampleExtractorFactory;
+        mConcurrentDvrPlaybackFlags = concurrentDvrPlaybackFlags;
     }
 
     @Override
@@ -70,9 +52,13 @@
         // Build the video and audio renderers.
         SampleExtractor extractor =
                 dataSource == null
-                        ? mMpegTsSampleExtractorFactory.create(mBufferManager, mBufferListener)
-                        : mMpegTsSampleExtractorFactory.create(
-                                dataSource, mBufferManager, mBufferListener);
+                        ? new MpegTsSampleExtractor(
+                                mBufferManager, mBufferListener, mConcurrentDvrPlaybackFlags)
+                        : new MpegTsSampleExtractor(
+                                dataSource,
+                                mBufferManager,
+                                mBufferListener,
+                                mConcurrentDvrPlaybackFlags);
         SampleSource sampleSource = new MpegTsSampleSource(extractor);
         MpegTsVideoTrackRenderer videoRenderer =
                 new MpegTsVideoTrackRenderer(
diff --git a/tuner/src/com/android/tv/tuner/exoplayer/MpegTsSampleExtractor.java b/tuner/src/com/android/tv/tuner/exoplayer/MpegTsSampleExtractor.java
index 8d3668e..582f18c 100644
--- a/tuner/src/com/android/tv/tuner/exoplayer/MpegTsSampleExtractor.java
+++ b/tuner/src/com/android/tv/tuner/exoplayer/MpegTsSampleExtractor.java
@@ -18,21 +18,16 @@
 
 import android.net.Uri;
 import android.os.Handler;
-import android.support.annotation.Nullable;
-
 import com.android.tv.tuner.exoplayer.buffer.BufferManager;
 import com.android.tv.tuner.exoplayer.buffer.PlaybackBufferListener;
 import com.android.tv.tuner.exoplayer.buffer.SamplePool;
-
 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.upstream.DataSource;
 import com.google.android.exoplayer.util.MimeTypes;
-import com.google.android.exoplayer2.upstream.DataSource;
-import com.google.auto.factory.AutoFactory;
-import com.google.auto.factory.Provided;
-
+import com.android.tv.common.flags.ConcurrentDvrPlaybackFlags;
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
@@ -64,37 +59,27 @@
     }
 
     /**
-     * Factory for {@link MpegTsSampleExtractor}.
-     *
-     * <p>This wrapper class keeps other classes from needing to reference the {@link AutoFactory}
-     * generated class.
-     */
-    public interface Factory {
-        public MpegTsSampleExtractor create(
-                BufferManager bufferManager, PlaybackBufferListener bufferListener);
-
-        public MpegTsSampleExtractor create(
-                DataSource source,
-                @Nullable BufferManager bufferManager,
-                PlaybackBufferListener bufferListener);
-    }
-
-    /**
-     * Creates MpegTsSampleExtractor for a {@link DataSource}.
+     * Creates MpegTsSampleExtractor for {@link DataSource}.
      *
      * @param source the {@link DataSource} to extract from
      * @param bufferManager the manager for reading & writing samples backed by physical storage
      * @param bufferListener the {@link PlaybackBufferListener} to notify buffer storage status
+     * @param concurrentDvrPlaybackFlags
      */
-    @AutoFactory(implementing = Factory.class)
     public MpegTsSampleExtractor(
             DataSource source,
-            @Nullable BufferManager bufferManager,
+            BufferManager bufferManager,
             PlaybackBufferListener bufferListener,
-            @Provided ExoPlayerSampleExtractor.Factory exoPlayerSampleExtractorFactory) {
+            ConcurrentDvrPlaybackFlags concurrentDvrPlaybackFlags) {
+
         mSampleExtractor =
-                exoPlayerSampleExtractorFactory.create(
-                        Uri.EMPTY, source, bufferManager, bufferListener, false);
+                new ExoPlayerSampleExtractor(
+                        Uri.EMPTY,
+                        source,
+                        bufferManager,
+                        bufferListener,
+                        false,
+                        concurrentDvrPlaybackFlags);
         init();
     }
 
@@ -105,12 +90,12 @@
      * @param bufferListener the {@link PlaybackBufferListener} to notify buffer storage status
      *     change
      */
-    @AutoFactory(implementing = Factory.class)
     public MpegTsSampleExtractor(
             BufferManager bufferManager,
             PlaybackBufferListener bufferListener,
-            @Provided FileSampleExtractor.Factory fileSampleExtractorFactory) {
-        mSampleExtractor = fileSampleExtractorFactory.create(bufferManager, bufferListener);
+            ConcurrentDvrPlaybackFlags concurrentDvrPlaybackFlags) {
+        mSampleExtractor =
+                new FileSampleExtractor(bufferManager, bufferListener, concurrentDvrPlaybackFlags);
         init();
     }
 
diff --git a/tuner/src/com/android/tv/tuner/exoplayer/audio/MpegTsDefaultAudioTrackRenderer.java b/tuner/src/com/android/tv/tuner/exoplayer/audio/MpegTsDefaultAudioTrackRenderer.java
index fb88e5b..bab74c9 100644
--- a/tuner/src/com/android/tv/tuner/exoplayer/audio/MpegTsDefaultAudioTrackRenderer.java
+++ b/tuner/src/com/android/tv/tuner/exoplayer/audio/MpegTsDefaultAudioTrackRenderer.java
@@ -246,7 +246,6 @@
         mSource.seekToUs(positionUs);
         AUDIO_TRACK.reset();
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
-            // b/21824483 workaround
             // resetSessionId() will create a new framework AudioTrack instead of reusing old one.
             AUDIO_TRACK.resetSessionId();
         }
@@ -285,7 +284,6 @@
                 // Ensure playback stops, after EoS was notified.
                 // Sometimes MediaCodecTrackRenderer does not fetch EoS timely
                 // after EoS was notified here long before.
-                // see b/21909113
                 long diff = SystemClock.elapsedRealtime() - mEndOfStreamMs;
                 if (diff >= KEEP_ALIVE_AFTER_EOS_DURATION_MS && !mIsStopped) {
                     throw new ExoPlaybackException("Much time has elapsed after EoS");
@@ -594,7 +592,6 @@
             }
             mCurrentPositionUs = Math.max(mPresentationTimeUs, mCurrentPositionUs);
         } else {
-            // TODO: Remove this workaround when b/22023809 is resolved.
             if (mPreviousPositionUs
                     > audioTrackCurrentPositionUs + BACKWARD_AUDIO_TRACK_MOVE_THRESHOLD_US) {
                 Log.e(
diff --git a/tuner/src/com/android/tv/tuner/exoplayer/buffer/BufferManager.java b/tuner/src/com/android/tv/tuner/exoplayer/buffer/BufferManager.java
index b8d8523..c32540c 100644
--- a/tuner/src/com/android/tv/tuner/exoplayer/buffer/BufferManager.java
+++ b/tuner/src/com/android/tv/tuner/exoplayer/buffer/BufferManager.java
@@ -23,13 +23,10 @@
 import android.util.ArrayMap;
 import android.util.Log;
 import android.util.Pair;
-
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.common.util.CommonUtils;
 import com.android.tv.tuner.exoplayer.SampleExtractor;
-
 import com.google.android.exoplayer.SampleHolder;
-
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
@@ -403,13 +400,13 @@
             SampleChunk sampleChunk =
                     mSampleChunkCreator.createSampleChunk(
                             samplePool, file, positionUs, mChunkCallback);
-            map.put(positionUs, Pair.create(sampleChunk, 0));
+            map.put(positionUs, new Pair(sampleChunk, 0));
             if (updateIndexFile) {
                 mStorageManager.updateIndexFile(id, map.size(), positionUs, sampleChunk, 0);
             }
             return sampleChunk;
         } else {
-            map.put(positionUs, Pair.create(currentChunk, currentOffset));
+            map.put(positionUs, new Pair(currentChunk, currentOffset));
             if (updateIndexFile) {
                 mStorageManager.updateIndexFile(
                         id, map.size(), positionUs, currentChunk, currentOffset);
@@ -450,7 +447,7 @@
                                 chunk);
                 basePositionUs = position.basePositionUs;
             }
-            map.put(position.positionUs, Pair.create(chunk, position.offset));
+            map.put(position.positionUs, new Pair(chunk, position.offset));
         }
     }
 
diff --git a/tuner/src/com/android/tv/tuner/exoplayer/buffer/DvrStorageManager.java b/tuner/src/com/android/tv/tuner/exoplayer/buffer/DvrStorageManager.java
index 0e1cbe9..f19756e 100644
--- a/tuner/src/com/android/tv/tuner/exoplayer/buffer/DvrStorageManager.java
+++ b/tuner/src/com/android/tv/tuner/exoplayer/buffer/DvrStorageManager.java
@@ -19,7 +19,8 @@
 import android.media.MediaFormat;
 import android.util.Log;
 import android.util.Pair;
-import com.android.tv.tuner.data.Track.AtscCaptionTrack;
+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;
@@ -368,7 +369,7 @@
                     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))) {
-                track.writeTo(out);
+                out.write(MessageNano.toByteArray(track));
             } catch (Exception e) {
                 Log.e(TAG, "Fail to write caption info to files", e);
             }
diff --git a/tuner/src/com/android/tv/tuner/exoplayer/buffer/RecordingSampleBuffer.java b/tuner/src/com/android/tv/tuner/exoplayer/buffer/RecordingSampleBuffer.java
index df2cd2e..d95642c 100644
--- a/tuner/src/com/android/tv/tuner/exoplayer/buffer/RecordingSampleBuffer.java
+++ b/tuner/src/com/android/tv/tuner/exoplayer/buffer/RecordingSampleBuffer.java
@@ -20,18 +20,14 @@
 import android.support.annotation.IntDef;
 import android.support.annotation.NonNull;
 import android.util.Log;
-
 import com.android.tv.tuner.exoplayer.MpegTsPlayer;
 import com.android.tv.tuner.exoplayer.SampleExtractor;
-
 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.google.android.exoplayer.util.Assertions;
-import com.google.auto.factory.AutoFactory;
-import com.google.auto.factory.Provided;
-
+import com.android.tv.common.flags.ConcurrentDvrPlaybackFlags;
 import java.io.IOException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -73,7 +69,7 @@
     private final BufferManager mBufferManager;
     private final PlaybackBufferListener mBufferListener;
     private final @BufferReason int mBufferReason;
-    private final SampleChunkIoHelper.Factory mSampleChunkIoHelperFactory;
+    private final ConcurrentDvrPlaybackFlags mConcurrentDvrPlaybackFlags;
 
     private int mTrackCount;
     private boolean[] mTrackSelected;
@@ -102,42 +98,28 @@
             };
 
     /**
-     * Factory for {@link RecordingSampleBuffer}.
-     *
-     * <p>This wrapper class keeps other classes from needing to reference the {@link AutoFactory}
-     * generated class.
-     */
-    public interface Factory {
-        public RecordingSampleBuffer create(
-                BufferManager bufferManager,
-                PlaybackBufferListener bufferListener,
-                boolean enableTrickplay,
-                @BufferReason int bufferReason);
-    }
-
-    /**
      * Creates {@link BufferManager.SampleBuffer} with cached I/O backed by physical storage (e.g.
      * trickplay,recording,recorded-playback).
      *
      * @param bufferManager the manager of {@link SampleChunk}
      * @param bufferListener the listener for buffer I/O event
      * @param enableTrickplay {@code true} when trickplay should be enabled
+     * @param concurrentDvrPlaybackFlags
      * @param bufferReason the reason for caching samples {@link BufferReason}
      */
-    @AutoFactory(implementing = Factory.class)
     public RecordingSampleBuffer(
             BufferManager bufferManager,
             PlaybackBufferListener bufferListener,
             boolean enableTrickplay,
-            @BufferReason int bufferReason,
-            @Provided SampleChunkIoHelper.Factory sampleChunkIoHelperFactory) {
+            ConcurrentDvrPlaybackFlags concurrentDvrPlaybackFlags,
+            @BufferReason int bufferReason) {
         mBufferManager = bufferManager;
         mBufferListener = bufferListener;
+        mConcurrentDvrPlaybackFlags = concurrentDvrPlaybackFlags;
         if (bufferListener != null) {
             bufferListener.onBufferStateChanged(enableTrickplay);
         }
         mBufferReason = bufferReason;
-        mSampleChunkIoHelperFactory = sampleChunkIoHelperFactory;
     }
 
     @Override
@@ -150,8 +132,14 @@
         mTrackSelected = new boolean[mTrackCount];
         mReadSampleQueues = new ArrayList<>();
         mSampleChunkIoHelper =
-                mSampleChunkIoHelperFactory.create(
-                        ids, mediaFormats, mBufferReason, mBufferManager, mSamplePool, mIoCallback);
+                new SampleChunkIoHelper(
+                        ids,
+                        mediaFormats,
+                        mBufferReason,
+                        mBufferManager,
+                        mSamplePool,
+                        mIoCallback,
+                        mConcurrentDvrPlaybackFlags);
         for (int i = 0; i < mTrackCount; ++i) {
             mReadSampleQueues.add(i, new SampleQueue(mSamplePool));
         }
diff --git a/tuner/src/com/android/tv/tuner/exoplayer/buffer/SampleChunkIoHelper.java b/tuner/src/com/android/tv/tuner/exoplayer/buffer/SampleChunkIoHelper.java
index 82bf0df..f4d3bf8 100644
--- a/tuner/src/com/android/tv/tuner/exoplayer/buffer/SampleChunkIoHelper.java
+++ b/tuner/src/com/android/tv/tuner/exoplayer/buffer/SampleChunkIoHelper.java
@@ -24,17 +24,12 @@
 import android.util.ArraySet;
 import android.util.Log;
 import android.util.Pair;
-
 import com.android.tv.common.SoftPreconditions;
-import com.android.tv.common.flags.DvrFlags;
 import com.android.tv.tuner.exoplayer.buffer.RecordingSampleBuffer.BufferReason;
-
 import com.google.android.exoplayer.MediaFormat;
 import com.google.android.exoplayer.SampleHolder;
 import com.google.android.exoplayer.util.MimeTypes;
-import com.google.auto.factory.AutoFactory;
-import com.google.auto.factory.Provided;
-
+import com.android.tv.common.flags.ConcurrentDvrPlaybackFlags;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.LinkedList;
@@ -69,7 +64,7 @@
     private final BufferManager mBufferManager;
     private final SamplePool mSamplePool;
     private final IoCallback mIoCallback;
-    private final DvrFlags mDvrFlags;
+    private final ConcurrentDvrPlaybackFlags mConcurrentDvrPlaybackFlags;
 
     private Handler mIoHandler;
     private final ConcurrentLinkedQueue<SampleHolder> mReadSampleBuffers[];
@@ -118,22 +113,6 @@
     }
 
     /**
-     * Factory for {@link SampleChunkIoHelper}.
-     *
-     * <p>This wrapper class keeps other classes from needing to reference the {@link AutoFactory}
-     * generated class.
-     */
-    public interface Factory {
-        public SampleChunkIoHelper create(
-                List<String> ids,
-                List<MediaFormat> mediaFormats,
-                @BufferReason int bufferReason,
-                BufferManager bufferManager,
-                SamplePool samplePool,
-                IoCallback ioCallback);
-    }
-
-    /**
      * Creates {@link SampleChunk} I/O handler.
      *
      * @param ids track names
@@ -142,8 +121,8 @@
      * @param bufferManager manager of {@link SampleChunk} collections
      * @param samplePool allocator for a sample
      * @param ioCallback listeners for I/O events
+     * @param concurrentDvrPlaybackFlags
      */
-    @AutoFactory(implementing = Factory.class)
     public SampleChunkIoHelper(
             List<String> ids,
             List<MediaFormat> mediaFormats,
@@ -151,7 +130,7 @@
             BufferManager bufferManager,
             SamplePool samplePool,
             IoCallback ioCallback,
-            @Provided DvrFlags dvrFlags) {
+            ConcurrentDvrPlaybackFlags concurrentDvrPlaybackFlags) {
         mTrackCount = ids.size();
         mIds = ids;
         mMediaFormats = mediaFormats;
@@ -159,7 +138,7 @@
         mBufferManager = bufferManager;
         mSamplePool = samplePool;
         mIoCallback = ioCallback;
-        mDvrFlags = dvrFlags;
+        mConcurrentDvrPlaybackFlags = concurrentDvrPlaybackFlags;
 
         mReadSampleBuffers = new ConcurrentLinkedQueue[mTrackCount];
         mHandlerReadSampleBuffers = new ConcurrentLinkedQueue[mTrackCount];
@@ -205,7 +184,9 @@
         }
 
         try {
-            if (mBufferReason == RecordingSampleBuffer.BUFFER_REASON_RECORDING && mTrackCount > 0) {
+            if (mConcurrentDvrPlaybackFlags.enabled()
+                    && mBufferReason == RecordingSampleBuffer.BUFFER_REASON_RECORDING
+                    && mTrackCount > 0) {
                 // Saves meta information for recording.
                 List<BufferManager.TrackFormat> audios = new ArrayList<>(mTrackCount);
                 List<BufferManager.TrackFormat> videos = new ArrayList<>(mTrackCount);
@@ -213,14 +194,6 @@
                     android.media.MediaFormat format =
                             mMediaFormats.get(i).getFrameworkMediaFormatV16();
                     format.setLong(android.media.MediaFormat.KEY_DURATION, mBufferDurationUs);
-                    if (mDvrFlags.storeVideoAspectRatio() &&
-                            mMediaFormats.get(i).pixelWidthHeightRatio > 0) {
-                        // MediaFormats doesn't store aspect ratio so updating the width
-                        // to maintain aspect ratio.
-                        format.setInteger(android.media.MediaFormat.KEY_WIDTH,
-                                (int) (mMediaFormats.get(i).width *
-                                        mMediaFormats.get(i).pixelWidthHeightRatio));
-                    }
                     if (MimeTypes.isAudio(mMediaFormats.get(i).mimeType)) {
                         audios.add(new BufferManager.TrackFormat(mIds.get(i), format));
                     } else if (MimeTypes.isVideo(mMediaFormats.get(i).mimeType)) {
@@ -329,14 +302,6 @@
                     android.media.MediaFormat format =
                             mMediaFormats.get(i).getFrameworkMediaFormatV16();
                     format.setLong(android.media.MediaFormat.KEY_DURATION, mBufferDurationUs);
-                    if (mDvrFlags.storeVideoAspectRatio() &&
-                            mMediaFormats.get(i).pixelWidthHeightRatio > 0) {
-                        // MediaFormats doesn't store aspect ratio so updating the width
-                        // to maintain aspect ratio.
-                        format.setInteger(android.media.MediaFormat.KEY_WIDTH,
-                                (int) (mMediaFormats.get(i).width *
-                                        mMediaFormats.get(i).pixelWidthHeightRatio));
-                    }
                     if (MimeTypes.isAudio(mMediaFormats.get(i).mimeType)) {
                         audios.add(new BufferManager.TrackFormat(mIds.get(i), format));
                     } else if (MimeTypes.isVideo(mMediaFormats.get(i).mimeType)) {
@@ -419,7 +384,8 @@
 
     private void doOpenWrite(int index) throws IOException {
         boolean updateIndexFile =
-                (mBufferReason == RecordingSampleBuffer.BUFFER_REASON_RECORDING)
+                mConcurrentDvrPlaybackFlags.enabled()
+                        && (mBufferReason == RecordingSampleBuffer.BUFFER_REASON_RECORDING)
                         && (MimeTypes.isVideo(mMediaFormats.get(index).mimeType)
                                 || MimeTypes.isAudio(mMediaFormats.get(index).mimeType));
 
@@ -460,10 +426,13 @@
             SampleHolder sample = mReadIoStates[index].read();
             if (sample != null) {
                 mHandlerReadSampleBuffers[index].offer(sample);
-                mReadChunkOffset[index] = mReadIoStates[index].getOffset();
-                mReadChunkPositionUs[index] = sample.timeUs;
+                if (mConcurrentDvrPlaybackFlags.enabled()) {
+                    mReadChunkOffset[index] = mReadIoStates[index].getOffset();
+                    mReadChunkPositionUs[index] = sample.timeUs;
+                }
             } else {
-                if (mBufferReason == RecordingSampleBuffer.BUFFER_REASON_RECORDED_PLAYBACK) {
+                if (mConcurrentDvrPlaybackFlags.enabled()
+                        && mBufferReason == RecordingSampleBuffer.BUFFER_REASON_RECORDED_PLAYBACK) {
                     // Update Index, to load new Samples
                     updateIndex(index, mReadChunkOffset[index]);
                 }
@@ -516,7 +485,9 @@
                                     : mWriteIoStates[params.index].getChunk();
                     int currentOffset = (int) mWriteIoStates[params.index].getOffset();
                     boolean updateIndexFile =
-                            (mBufferReason == RecordingSampleBuffer.BUFFER_REASON_RECORDING)
+                            mConcurrentDvrPlaybackFlags.enabled()
+                                    && (mBufferReason
+                                            == RecordingSampleBuffer.BUFFER_REASON_RECORDING)
                                     && (MimeTypes.isVideo(mMediaFormats.get(index).mimeType)
                                             || MimeTypes.isAudio(
                                                     mMediaFormats.get(index).mimeType));
diff --git a/tuner/src/com/android/tv/tuner/exoplayer2/VideoRendererExoV2.java b/tuner/src/com/android/tv/tuner/exoplayer2/VideoRendererExoV2.java
index a71352f..1203900 100644
--- a/tuner/src/com/android/tv/tuner/exoplayer2/VideoRendererExoV2.java
+++ b/tuner/src/com/android/tv/tuner/exoplayer2/VideoRendererExoV2.java
@@ -24,6 +24,7 @@
 import com.google.android.exoplayer2.mediacodec.MediaCodecInfo;
 import com.google.android.exoplayer2.mediacodec.MediaCodecSelector;
 import com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException;
+import com.google.android.exoplayer2.util.MimeTypes;
 import com.google.android.exoplayer2.video.MediaCodecVideoRenderer;
 import com.google.android.exoplayer2.video.VideoRendererEventListener;
 import java.lang.reflect.Field;
@@ -47,8 +48,8 @@
     private static final String SOFTWARE_DECODER_NAME_PREFIX = "OMX.google.";
     private static final long ALLOWED_JOINING_TIME_MS = 5000;
     private static final int DROPPED_FRAMES_NOTIFICATION_THRESHOLD = 10;
-  // private static final int MIN_HD_HEIGHT = 720;
-  private static Field sRenderedFirstFrameField;
+    private static final int MIN_HD_HEIGHT = 720;
+    private static Field sRenderedFirstFrameField;
 
     private final boolean mIsSwCodecEnabled;
     private boolean mCodecIsSwPreferred;
@@ -107,18 +108,16 @@
         return decoderInfos;
     }
 
-  // TODO: Uncomment once ExoPlayer v2.10.0 is released [Internal ref: b/130625979].
-  // @Override
-  // protected void onInputFormatChanged(FormatHolder formatHolder) throws ExoPlaybackException {
-  //     Format format = formatHolder.format;
-  //     mCodecIsSwPreferred =
-  //             MimeTypes.VIDEO_MPEG2.equals(format.sampleMimeType)
-  //                     && format.height < MIN_HD_HEIGHT;
-  //     super.onInputFormatChanged(format);
-  // }
+    @Override
+    protected void onInputFormatChanged(Format format) throws ExoPlaybackException {
+        mCodecIsSwPreferred =
+                MimeTypes.VIDEO_MPEG2.equals(format.sampleMimeType)
+                        && format.height < MIN_HD_HEIGHT;
+        super.onInputFormatChanged(format);
+    }
 
-  @Override
-  protected void onPositionReset(long positionUs, boolean joining) throws ExoPlaybackException {
+    @Override
+    protected void onPositionReset(long positionUs, boolean joining) throws ExoPlaybackException {
         super.onPositionReset(positionUs, joining);
         // Disabling pre-rendering of the first frame in order to avoid a frozen picture when
         // starting the playback. We do this only once, when the renderer is enabled at first, since
diff --git a/tuner/src/com/android/tv/tuner/features/TunerFeatures.java b/tuner/src/com/android/tv/tuner/features/TunerFeatures.java
index 6ee5aa8..6033a3a 100644
--- a/tuner/src/com/android/tv/tuner/features/TunerFeatures.java
+++ b/tuner/src/com/android/tv/tuner/features/TunerFeatures.java
@@ -19,9 +19,9 @@
 import static com.android.tv.common.feature.FeatureUtils.OFF;
 
 import com.android.tv.common.feature.CommonFeatures;
-import com.android.tv.common.feature.DeveloperPreferenceFeature;
 import com.android.tv.common.feature.Feature;
 import com.android.tv.common.feature.Model;
+import com.android.tv.common.feature.PropertyFeature;
 import com.android.tv.common.feature.Sdk;
 
 /**
@@ -39,11 +39,10 @@
      * <p>Prefer software based codec for SD channels.
      */
     public static final Feature USE_SW_CODEC_FOR_SD =
-            DeveloperPreferenceFeature.create(
+            PropertyFeature.create(
                     "use_sw_codec_for_sd",
-                    // On Nexus Player, SW codec is better than HW codec in terms of picture
-                    // quality.
-                    Model.NEXUS_PLAYER.isEnabled());
+                    false
+                    );
 
     /**
      * Does the TvProvider on the installed device allow systems inserts to the programs table.
diff --git a/tuner/src/com/android/tv/tuner/hdhomerun/HdHomeRunChannelScan.java b/tuner/src/com/android/tv/tuner/hdhomerun/HdHomeRunChannelScan.java
deleted file mode 100644
index 38610dd..0000000
--- a/tuner/src/com/android/tv/tuner/hdhomerun/HdHomeRunChannelScan.java
+++ /dev/null
@@ -1,206 +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.tuner.hdhomerun;
-
-import android.content.Context;
-import android.media.tv.TvContract;
-import android.os.ConditionVariable;
-import android.util.Log;
-import android.util.Xml;
-import com.android.tv.tuner.api.ChannelScanListener;
-import com.android.tv.tuner.data.TunerChannel;
-import com.android.tv.tuner.ts.EventDetector.EventListener;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.util.regex.Pattern;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-/** A helper class to perform channel scan on HDHomeRun tuner. */
-public class HdHomeRunChannelScan {
-    private static final String TAG = "HdHomeRunChannelScan";
-    private static final boolean DEBUG = false;
-
-    private static final String LINEUP_FILENAME = "lineup.xml";
-    private static final String NAME_LINEUP = "Lineup";
-    private static final String NAME_PROGRAM = "Program";
-    private static final String NAME_GUIDE_NUMBER = "GuideNumber";
-    private static final String NAME_GUIDE_NAME = "GuideName";
-    private static final String NAME_HD = "HD";
-    private static final String NAME_TAGS = "Tags";
-    private static final String NAME_DRM = "DRM";
-
-    private final Context mContext;
-    private final ChannelScanListener mEventListener;
-    private final HdHomeRunTunerHal mTunerHal;
-    private int mProgramCount;
-
-    public HdHomeRunChannelScan(
-            Context context, EventListener eventListener, HdHomeRunTunerHal hal) {
-        mContext = context;
-        mEventListener = eventListener;
-        mTunerHal = hal;
-    }
-
-    public void scan(ConditionVariable conditionStopped) {
-        String urlString = "http://" + mTunerHal.getIpAddress() + "/" + LINEUP_FILENAME;
-        if (DEBUG) Log.d(TAG, "Reading " + urlString);
-        URL url;
-        HttpURLConnection connection = null;
-        InputStream inputStream;
-        try {
-            url = new URL(urlString);
-            connection = (HttpURLConnection) url.openConnection();
-            connection.setReadTimeout(HdHomeRunTunerHal.READ_TIMEOUT_MS_FOR_URLCONNECTION);
-            connection.setConnectTimeout(HdHomeRunTunerHal.CONNECTION_TIMEOUT_MS_FOR_URLCONNECTION);
-            connection.setRequestMethod("GET");
-            connection.setDoInput(true);
-            connection.connect();
-            inputStream = connection.getInputStream();
-        } catch (IOException e) {
-            Log.e(TAG, "Connection failed: " + urlString, e);
-            if (connection != null) {
-                connection.disconnect();
-            }
-            return;
-        }
-        if (conditionStopped.block(-1)) {
-            try {
-                inputStream.close();
-            } catch (IOException e) {
-                // Does nothing.
-            }
-            connection.disconnect();
-            return;
-        }
-
-        XmlPullParser parser = Xml.newPullParser();
-        try {
-            parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
-            parser.setInput(inputStream, null);
-            parser.nextTag();
-            parser.require(XmlPullParser.START_TAG, null, NAME_LINEUP);
-            while (parser.next() != XmlPullParser.END_TAG) {
-                if (conditionStopped.block(-1)) {
-                    break;
-                }
-                if (parser.getEventType() != XmlPullParser.START_TAG) {
-                    continue;
-                }
-                String name = parser.getName();
-                // Starts by looking for the program tag
-                if (name.equals(NAME_PROGRAM)) {
-                    readProgram(parser);
-                } else {
-                    skip(parser);
-                }
-            }
-            inputStream.close();
-        } catch (IOException | XmlPullParserException e) {
-            Log.e(TAG, "Parse error", e);
-        }
-        connection.disconnect();
-        mTunerHal.markAsScannedDevice(mContext);
-    }
-
-    private void readProgram(XmlPullParser parser) throws XmlPullParserException, IOException {
-        parser.require(XmlPullParser.START_TAG, null, NAME_PROGRAM);
-        String guideNumber = "";
-        String guideName = "";
-        String videoFormat = null;
-        String tags = "";
-        boolean recordingProhibited = false;
-        while (parser.next() != XmlPullParser.END_TAG) {
-            if (parser.getEventType() != XmlPullParser.START_TAG) {
-                continue;
-            }
-            String name = parser.getName();
-            if (name.equals(NAME_GUIDE_NUMBER)) {
-                guideNumber = readText(parser, NAME_GUIDE_NUMBER);
-            } else if (name.equals(NAME_GUIDE_NAME)) {
-                guideName = readText(parser, NAME_GUIDE_NAME);
-            } else if (name.equals(NAME_HD)) {
-                videoFormat = TvContract.Channels.VIDEO_FORMAT_720P;
-                skip(parser);
-            } else if (name.equals(NAME_TAGS)) {
-                tags = readText(parser, NAME_TAGS);
-            } else if (name.equals(NAME_DRM)) {
-                String drm = readText(parser, NAME_DRM);
-                try {
-                    recordingProhibited = (Integer.parseInt(drm)) != 0;
-                } catch (NumberFormatException e) {
-                    Log.e(TAG, "Load DRM property failed: illegal number: " + drm);
-                    // If DRM property is present, we treat it as copy-once or copy-never.
-                    recordingProhibited = true;
-                }
-            } else {
-                skip(parser);
-            }
-        }
-        if (!tags.isEmpty()) {
-            // Skip encrypted channels since we don't know how to decrypt them.
-            return;
-        }
-        int major;
-        int minor = 0;
-        final String separator = Character.toString(HdHomeRunTunerHal.VCHANNEL_SEPARATOR);
-        if (guideNumber.contains(separator)) {
-            String[] parts = guideNumber.split(Pattern.quote(separator));
-            major = Integer.parseInt(parts[0]);
-            minor = Integer.parseInt(parts[1]);
-        } else {
-            major = Integer.parseInt(guideNumber);
-        }
-        // Need to assign a unique program number (i.e. mProgramCount) to avoid being duplicated.
-        mEventListener.onChannelDetected(
-                TunerChannel.forNetwork(
-                        major, minor, mProgramCount++, guideName, recordingProhibited, videoFormat),
-                true);
-    }
-
-    private String readText(XmlPullParser parser, String name)
-            throws IOException, XmlPullParserException {
-        String result = "";
-        parser.require(XmlPullParser.START_TAG, null, name);
-        if (parser.next() == XmlPullParser.TEXT) {
-            result = parser.getText();
-            parser.nextTag();
-        }
-        parser.require(XmlPullParser.END_TAG, null, name);
-        if (DEBUG) Log.d(TAG, "<" + name + ">=" + result);
-        return result;
-    }
-
-    private void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
-        if (parser.getEventType() != XmlPullParser.START_TAG) {
-            throw new IllegalStateException();
-        }
-        int depth = 1;
-        while (depth != 0) {
-            switch (parser.next()) {
-                case XmlPullParser.END_TAG:
-                    depth--;
-                    break;
-                case XmlPullParser.START_TAG:
-                    depth++;
-                    break;
-            }
-        }
-    }
-}
diff --git a/tuner/src/com/android/tv/tuner/hdhomerun/HdHomeRunControlSocket.java b/tuner/src/com/android/tv/tuner/hdhomerun/HdHomeRunControlSocket.java
deleted file mode 100644
index ce7c518..0000000
--- a/tuner/src/com/android/tv/tuner/hdhomerun/HdHomeRunControlSocket.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * 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.hdhomerun;
-
-import android.support.annotation.Nullable;
-import android.util.Log;
-import android.util.Pair;
-import com.android.tv.tuner.hdhomerun.HdHomeRunDiscover.HdHomeRunDiscoverDevice;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * A class to send/receive control commands and results to/from HDHomeRun devices via TCP sockets.
- * {@link #close()} method should be called after usage to close the TCP socket.
- */
-class HdHomeRunControlSocket implements AutoCloseable {
-    private static final String TAG = "HdHomeRunControlSocket";
-    private static final boolean DEBUG = false;
-
-    private int mDesiredDeviceId;
-    private int mDesiredDeviceIp;
-    private int mActualDeviceId;
-    private int mActualDeviceIp;
-    private Socket mSocket;
-
-    HdHomeRunControlSocket(int deviceId, int deviceIp) {
-        mDesiredDeviceId = deviceId;
-        mDesiredDeviceIp = deviceIp;
-        mActualDeviceId = 0;
-        mActualDeviceIp = 0;
-    }
-
-    /**
-     * Gets control settings from HDHomeRun devices.
-     *
-     * @param name the name of the field whose value we want to get.
-     */
-    @Nullable
-    String get(String name) {
-        byte[] data = new byte[name.length() + 3];
-        ByteBuffer buffer = ByteBuffer.wrap(data);
-        buffer.put(HdHomeRunUtils.HDHOMERUN_TAG_GETSET_NAME);
-        buffer.put((byte) (name.length() + 1));
-        buffer.put(name.getBytes());
-
-        // Send & Receive.
-        byte[] result =
-                sendAndReceive(
-                        data,
-                        HdHomeRunUtils.HDHOMERUN_TYPE_GETSET_REQUEST,
-                        HdHomeRunUtils.HDHOMERUN_CONTROL_RECEIVE_TIMEOUT_MS);
-        if (result == null) {
-            if (DEBUG) Log.d(TAG, "Cannot get result for " + name);
-            return null;
-        }
-
-        // Response.
-        buffer = ByteBuffer.wrap(result);
-        while (true) {
-            Pair<Byte, byte[]> tagAndValue = HdHomeRunUtils.readTaggedValue(buffer);
-            if (tagAndValue == null) {
-                break;
-            }
-            switch (tagAndValue.first) {
-                case HdHomeRunUtils.HDHOMERUN_TAG_GETSET_VALUE:
-                    // Removes the 0 tail.
-                    return new String(
-                            Arrays.copyOfRange(
-                                    tagAndValue.second, 0, tagAndValue.second.length - 1));
-                case HdHomeRunUtils.HDHOMERUN_TAG_ERROR_MESSAGE:
-                    return null;
-            }
-        }
-        return null;
-    }
-
-    /** Gets ID of HDHomeRun devices. */
-    int getDeviceId() {
-        if (!connectAndUpdateDeviceInfo()) {
-            return 0;
-        }
-        return mActualDeviceId;
-    }
-
-    private boolean connectAndUpdateDeviceInfo() {
-        if (mSocket != null) {
-            return true;
-        }
-        if ((mDesiredDeviceId == 0) && (mDesiredDeviceIp == 0)) {
-            if (DEBUG) Log.d(TAG, "Desired ID and IP cannot be both zero.");
-            return false;
-        }
-        if (HdHomeRunUtils.isIpMulticast(mDesiredDeviceIp)) {
-            if (DEBUG) Log.d(TAG, "IP cannot be multicast IP.");
-            return false;
-        }
-
-        // Find device.
-        List<HdHomeRunDiscoverDevice> result =
-                HdHomeRunUtils.findHdHomeRunDevices(
-                        mDesiredDeviceIp,
-                        HdHomeRunUtils.HDHOMERUN_DEVICE_TYPE_WILDCARD,
-                        mDesiredDeviceId,
-                        1);
-        if (result.isEmpty()) {
-            if (DEBUG) Log.d(TAG, "Cannot find device on: " + mDesiredDeviceIp);
-            return false;
-        }
-        mActualDeviceIp = result.get(0).mIpAddress;
-        mActualDeviceId = result.get(0).mDeviceId;
-
-        // Create socket and initiate connection.
-        mSocket = new Socket();
-        try {
-            mSocket.connect(
-                    new InetSocketAddress(
-                            HdHomeRunUtils.intToAddress(mActualDeviceIp),
-                            HdHomeRunUtils.HDHOMERUN_CONTROL_TCP_PORT),
-                    HdHomeRunUtils.HDHOMERUN_CONTROL_CONNECT_TIMEOUT_MS);
-        } catch (IOException e) {
-            if (DEBUG) Log.d(TAG, "Cannot connect to socket: " + mSocket);
-            mSocket = null;
-            return false;
-        }
-
-        // Success.
-        Log.i(TAG, "Connected to socket: " + mSocket);
-        return true;
-    }
-
-    private byte[] sendAndReceive(byte[] data, short type, int timeout) {
-        byte[] sealedData = HdHomeRunUtils.sealFrame(data, type);
-        for (int i = 0; i < 2; i++) {
-            if (mSocket == null && !connectAndUpdateDeviceInfo()) {
-                return null;
-            }
-            if (!send(sealedData)) {
-                continue;
-            }
-            Pair<Short, byte[]> receivedData = receive(timeout);
-            if (receivedData == null || receivedData.first == null) {
-                continue;
-            }
-            if (receivedData.first != type + 1) {
-                if (DEBUG) Log.d(TAG, "Returned type incorrect: " + receivedData.first);
-                close();
-                continue;
-            }
-            return receivedData.second;
-        }
-        return null;
-    }
-
-    private boolean send(byte[] data) {
-        try {
-            OutputStream out = mSocket.getOutputStream();
-            mSocket.setSoTimeout(HdHomeRunUtils.HDHOMERUN_CONTROL_SEND_TIMEOUT_MS);
-            out.write(data);
-        } catch (IOException e) {
-            if (DEBUG) Log.d(TAG, "Cannot send packet to socket: " + mSocket);
-            close();
-            return false;
-        }
-        return true;
-    }
-
-    private Pair<Short, byte[]> receive(int timeout) {
-        byte[] receivedData = new byte[3074];
-        try {
-            InputStream input = mSocket.getInputStream();
-            mSocket.setSoTimeout(timeout);
-            int index = 0;
-            long startTime = System.currentTimeMillis();
-            while (System.currentTimeMillis() - startTime < timeout) {
-                int length = receivedData.length - index;
-                index += input.read(receivedData, index, length);
-                Pair<Short, byte[]> result = HdHomeRunUtils.openFrame(receivedData, index);
-                if (result != null) {
-                    if (result.first == HdHomeRunUtils.HDHOMERUN_TYPE_INVALID) {
-                        if (DEBUG) Log.d(TAG, "Returned type is invalid.");
-                        close();
-                        return null;
-                    }
-                    return result;
-                }
-                if (DEBUG) Log.d(TAG, "Received result is null!");
-            }
-        } catch (IOException e) {
-            if (DEBUG) Log.d(TAG, "Cannot receive from socket: " + mSocket);
-            close();
-        }
-        return null;
-    }
-
-    @Override
-    public void close() {
-        if (mSocket != null) {
-            try {
-                mSocket.close();
-            } catch (IOException e) {
-                // Do nothing
-            }
-            mSocket = null;
-        }
-    }
-}
diff --git a/tuner/src/com/android/tv/tuner/hdhomerun/HdHomeRunDevice.java b/tuner/src/com/android/tv/tuner/hdhomerun/HdHomeRunDevice.java
deleted file mode 100644
index dcf87ca..0000000
--- a/tuner/src/com/android/tv/tuner/hdhomerun/HdHomeRunDevice.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.tuner.hdhomerun;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-
-/**
- * An HDHomeRun device detected on the network. This abstraction only contains network data
- * necessary to establish a connection with the device and does not represent a communication
- * channel with the device itself. Currently, we only support devices with HTTP streaming
- * functionality.
- */
-public class HdHomeRunDevice implements Parcelable {
-    private int mIpAddress;
-    private int mDeviceType;
-    private int mDeviceId;
-    private int mTunerIndex;
-    private String mDeviceModel;
-
-    /**
-     * Creates {@code HdHomeRunDevice} object from a parcel.
-     *
-     * @param parcel The parcel to create {@code HdHomeRunDevice} object from.
-     */
-    public HdHomeRunDevice(Parcel parcel) {
-        mIpAddress = parcel.readInt();
-        mDeviceType = parcel.readInt();
-        mDeviceId = parcel.readInt();
-        mTunerIndex = parcel.readInt();
-        mDeviceModel = parcel.readString();
-    }
-
-    /**
-     * Creates {@code HdHomeRunDevice} object from IP address, device type, device ID and tuner
-     * index.
-     *
-     * @param ipAddress The IP address to create {@code HdHomeRunDevice} object from.
-     * @param deviceType The device type to create {@code HdHomeRunDevice} object from.
-     * @param deviceId The device ID to create {@code HdHomeRunDevice} object from.
-     * @param tunerIndex The tuner index to {@code HdHomeRunDevice} object from.
-     */
-    public HdHomeRunDevice(
-            int ipAddress, int deviceType, int deviceId, int tunerIndex, String deviceModel) {
-        mIpAddress = ipAddress;
-        mDeviceType = deviceType;
-        mDeviceId = deviceId;
-        mTunerIndex = tunerIndex;
-        mDeviceModel = deviceModel;
-    }
-
-    /**
-     * Returns the IP address.
-     *
-     * @return the IP address of this homerun device.
-     */
-    public int getIpAddress() {
-        return mIpAddress;
-    }
-
-    /**
-     * Returns the device type.
-     *
-     * @return the type of device for this homerun device.
-     */
-    public int getDeviceType() {
-        return mDeviceType;
-    }
-
-    /**
-     * Returns the device ID.
-     *
-     * @return the device ID of this homerun device.
-     */
-    public int getDeviceId() {
-        return mDeviceId;
-    }
-
-    /**
-     * Returns the tuner index.
-     *
-     * @return the tuner index of this homerun device.
-     */
-    public int getTunerIndex() {
-        return mTunerIndex;
-    }
-
-    /**
-     * Returns the device model.
-     *
-     * @return the device model of this homerun device.
-     */
-    public String getDeviceModel() {
-        return mDeviceModel;
-    }
-
-    @Override
-    public String toString() {
-        String ipAddress =
-                ""
-                        + ((mIpAddress >>> 24) & 0xff)
-                        + "."
-                        + ((mIpAddress >>> 16) & 0xff)
-                        + "."
-                        + ((mIpAddress >>> 8) & 0xff)
-                        + "."
-                        + (mIpAddress & 0xff);
-        return String.format("[%x-%d:%s]", mDeviceId, mTunerIndex, ipAddress);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeInt(mIpAddress);
-        out.writeInt(mDeviceType);
-        out.writeInt(mDeviceId);
-        out.writeInt(mTunerIndex);
-        out.writeString(mDeviceModel);
-    }
-
-    @Override
-    public int hashCode() {
-        int hash = 17;
-        hash = hash * 31 + getIpAddress();
-        hash = hash * 31 + getDeviceType();
-        hash = hash * 31 + getDeviceId();
-        hash = hash * 31 + getTunerIndex();
-        return hash;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (!(o instanceof HdHomeRunDevice)) {
-            return false;
-        }
-        HdHomeRunDevice rhs = (HdHomeRunDevice) o;
-        return rhs != null
-                && getIpAddress() == rhs.getIpAddress()
-                && getDeviceType() == rhs.getDeviceType()
-                && getDeviceId() == rhs.getDeviceId()
-                && getTunerIndex() == rhs.getTunerIndex()
-                && TextUtils.equals(getDeviceModel(), rhs.getDeviceModel());
-    }
-
-    public static final Parcelable.Creator<HdHomeRunDevice> CREATOR =
-            new Parcelable.Creator<HdHomeRunDevice>() {
-
-                @Override
-                public HdHomeRunDevice createFromParcel(Parcel in) {
-                    return new HdHomeRunDevice(in);
-                }
-
-                @Override
-                public HdHomeRunDevice[] newArray(int size) {
-                    return new HdHomeRunDevice[size];
-                }
-            };
-}
diff --git a/tuner/src/com/android/tv/tuner/hdhomerun/HdHomeRunDiscover.java b/tuner/src/com/android/tv/tuner/hdhomerun/HdHomeRunDiscover.java
deleted file mode 100644
index 85b3450..0000000
--- a/tuner/src/com/android/tv/tuner/hdhomerun/HdHomeRunDiscover.java
+++ /dev/null
@@ -1,446 +0,0 @@
-/*
- * 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.hdhomerun;
-
-import android.support.annotation.NonNull;
-import android.util.Log;
-import android.util.Pair;
-import java.io.IOException;
-import java.net.DatagramPacket;
-import java.net.DatagramSocket;
-import java.net.InetAddress;
-import java.net.InterfaceAddress;
-import java.net.NetworkInterface;
-import java.net.SocketException;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.List;
-
-/** A class to discover HDHomeRun devices on the network with UDP broadcasting. */
-class HdHomeRunDiscover {
-    private static final String TAG = "HdHomeRunDiscover";
-    private static final boolean DEBUG = false;
-
-    private static final int HDHOMERUN_DISCOVER_MAX_SOCK_COUNT = 16;
-    private static final int HDHOMERUN_DISCOVER_RETRY_LIMIT = 2;
-    private static final int HDHOMERUN_DISCOVER_TIMEOUT_MS = 500;
-    private static final int HDHOMERUN_DISCOVER_RECEIVE_WAITE_TIME_MS = 10;
-
-    private List<HdHomeRunDiscoverSocket> mSockets = new ArrayList<>();
-
-    /** Creates a discover object. If cannot add a default socket, return {@code null}. */
-    static HdHomeRunDiscover create() {
-        HdHomeRunDiscover hdHomeRunDiscover = new HdHomeRunDiscover();
-        // Create a routable socket (always first entry).
-        if (!hdHomeRunDiscover.addSocket(0, 0)) {
-            return null;
-        }
-        return hdHomeRunDiscover;
-    }
-
-    /** Closes and releases all sockets required by this discover object. */
-    void close() {
-        for (HdHomeRunDiscoverSocket discoverSocket : mSockets) {
-            discoverSocket.close();
-        }
-    }
-
-    /** Finds HDHomeRun devices. */
-    @NonNull
-    List<HdHomeRunDiscoverDevice> findDevices(
-            int targetIp, int deviceType, int deviceId, int maxCount) {
-        List<HdHomeRunDiscoverDevice> resultList = new ArrayList<>();
-        resetLocalIpSockets();
-        for (int retry = 0;
-                retry < HDHOMERUN_DISCOVER_RETRY_LIMIT && resultList.isEmpty();
-                retry++) {
-            int localIpSent = send(targetIp, deviceType, deviceId);
-            if (localIpSent == 0) {
-                if (DEBUG) {
-                    Log.d(TAG, "Cannot send to target ip: " + HdHomeRunUtils.getIpString(targetIp));
-                }
-                continue;
-            }
-            long timeout = System.currentTimeMillis() + HDHOMERUN_DISCOVER_TIMEOUT_MS * localIpSent;
-            while (System.currentTimeMillis() < timeout) {
-                HdHomeRunDiscoverDevice result = new HdHomeRunDiscoverDevice();
-                if (!receive(result)) {
-                    continue;
-                }
-                // Filter.
-                if (deviceType != HdHomeRunUtils.HDHOMERUN_DEVICE_TYPE_WILDCARD
-                        && deviceType != result.mDeviceType) {
-                    continue;
-                }
-                if (deviceId != HdHomeRunUtils.HDHOMERUN_DEVICE_ID_WILDCARD
-                        && deviceId != result.mDeviceId) {
-                    continue;
-                }
-                if (isObsoleteDevice(deviceId)) {
-                    continue;
-                }
-                // Ensure not already in list.
-                if (resultList.contains(result)) {
-                    continue;
-                }
-                // Add to list.
-                resultList.add(result);
-                if (resultList.size() >= maxCount) {
-                    break;
-                }
-            }
-        }
-        return resultList;
-    }
-
-    private boolean addSocket(int localIp, int subnetMask) {
-        for (int i = 1; i < mSockets.size(); i++) {
-            HdHomeRunDiscoverSocket discoverSocket = mSockets.get(i);
-            if ((discoverSocket.mLocalIp == localIp)
-                    && (discoverSocket.mSubnetMask == subnetMask)) {
-                discoverSocket.mDetected = true;
-                return true;
-            }
-        }
-        if (mSockets.size() >= HDHOMERUN_DISCOVER_MAX_SOCK_COUNT) {
-            return false;
-        }
-        DatagramSocket socket;
-        try {
-            socket = new DatagramSocket(0, HdHomeRunUtils.intToAddress(localIp));
-            socket.setBroadcast(true);
-        } catch (IOException e) {
-            if (DEBUG) Log.d(TAG, "Cannot create socket: " + HdHomeRunUtils.getIpString(localIp));
-            return false;
-        }
-        // Write socket entry.
-        mSockets.add(new HdHomeRunDiscoverSocket(socket, true, localIp, subnetMask));
-        return true;
-    }
-
-    private void resetLocalIpSockets() {
-        for (int i = 1; i < mSockets.size(); i++) {
-            mSockets.get(i).mDetected = false;
-            mSockets.get(i).mDiscoverPacketSent = false;
-        }
-        List<LocalIpInfo> ipInfoList = getLocalIpInfo(HDHOMERUN_DISCOVER_MAX_SOCK_COUNT);
-        for (LocalIpInfo ipInfo : ipInfoList) {
-            if (DEBUG) {
-                Log.d(
-                        TAG,
-                        "Add local IP: "
-                                + HdHomeRunUtils.getIpString(ipInfo.mIpAddress)
-                                + ", "
-                                + HdHomeRunUtils.getIpString(ipInfo.mSubnetMask));
-            }
-            addSocket(ipInfo.mIpAddress, ipInfo.mSubnetMask);
-        }
-        Iterator<HdHomeRunDiscoverSocket> iterator = mSockets.iterator();
-        while (iterator.hasNext()) {
-            HdHomeRunDiscoverSocket discoverSocket = iterator.next();
-            if (!discoverSocket.mDetected) {
-                discoverSocket.close();
-                iterator.remove();
-            }
-        }
-    }
-
-    private List<LocalIpInfo> getLocalIpInfo(int maxCount) {
-        Enumeration<NetworkInterface> interfaces;
-        try {
-            interfaces = NetworkInterface.getNetworkInterfaces();
-        } catch (SocketException e) {
-            return Collections.emptyList();
-        }
-        List<LocalIpInfo> result = new ArrayList<>();
-        while (interfaces.hasMoreElements()) {
-            NetworkInterface networkInterface = interfaces.nextElement();
-            for (InterfaceAddress interfaceAddress : networkInterface.getInterfaceAddresses()) {
-                InetAddress inetAddress = interfaceAddress.getAddress();
-                if (!inetAddress.isAnyLocalAddress()
-                        && !inetAddress.isLinkLocalAddress()
-                        && !inetAddress.isLoopbackAddress()
-                        && !inetAddress.isMulticastAddress()) {
-                    LocalIpInfo localIpInfo = new LocalIpInfo();
-                    localIpInfo.mIpAddress = HdHomeRunUtils.addressToInt(inetAddress.getAddress());
-                    localIpInfo.mSubnetMask =
-                            (0x7fffffff >> (31 - interfaceAddress.getNetworkPrefixLength()));
-                    result.add(localIpInfo);
-                    if (result.size() >= maxCount) {
-                        return result;
-                    }
-                }
-            }
-        }
-        return result;
-    }
-
-    private int send(int targetIp, int deviceType, int deviceId) {
-        return targetIp == 0
-                ? sendWildcardIp(deviceType, deviceId)
-                : sendTargetIp(targetIp, deviceType, deviceId);
-    }
-
-    private int sendWildcardIp(int deviceType, int deviceId) {
-        int localIpSent = 0;
-
-        // Send subnet broadcast using each local ip socket.
-        // This will work with multiple separate 169.254.x.x interfaces.
-        for (int i = 1; i < mSockets.size(); i++) {
-            HdHomeRunDiscoverSocket discoverSocket = mSockets.get(i);
-            int targetIp = discoverSocket.mLocalIp | ~discoverSocket.mSubnetMask;
-            if (DEBUG) Log.d(TAG, "Send: " + HdHomeRunUtils.getIpString(targetIp));
-            localIpSent += discoverSocket.send(targetIp, deviceType, deviceId) ? 1 : 0;
-        }
-        // If no local ip sockets then fall back to sending a global broadcast letting
-        // the OS choose the interface.
-        if (localIpSent == 0) {
-            if (DEBUG) Log.d(TAG, "Send: " + HdHomeRunUtils.getIpString(0xFFFFFFFF));
-            localIpSent = mSockets.get(0).send(0xFFFFFFFF, deviceType, deviceId) ? 1 : 0;
-        }
-        return localIpSent;
-    }
-
-    private int sendTargetIp(int targetIp, int deviceType, int deviceId) {
-        int localIpSent = 0;
-
-        // Send targeted packet from any local ip that is in the same subnet.
-        // This will work with multiple separate 169.254.x.x interfaces.
-        for (int i = 1; i < mSockets.size(); i++) {
-            HdHomeRunDiscoverSocket discoverSocket = mSockets.get(i);
-            if (discoverSocket.mSubnetMask == 0) {
-                continue;
-            }
-            if ((targetIp & discoverSocket.mSubnetMask)
-                    != (discoverSocket.mLocalIp & discoverSocket.mSubnetMask)) {
-                continue;
-            }
-            localIpSent += discoverSocket.send(targetIp, deviceType, deviceId) ? 1 : 0;
-        }
-        // If target IP does not match a local subnet then fall back to letting the OS choose
-        // the gateway interface.
-        if (localIpSent == 0) {
-            localIpSent = mSockets.get(0).send(targetIp, deviceType, deviceId) ? 1 : 0;
-        }
-        return localIpSent;
-    }
-
-    private boolean receive(HdHomeRunDiscoverDevice result) {
-        for (HdHomeRunDiscoverSocket discoverSocket : mSockets) {
-            if (discoverSocket.mDiscoverPacketSent && discoverSocket.receive(result)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private boolean isObsoleteDevice(int deviceId) {
-        switch (deviceId >> 20) {
-            case 0x100: /* TECH-US/TECH3-US */
-                return (deviceId < 0x10040000);
-            case 0x120: /* TECH3-EU */
-                return (deviceId < 0x12030000);
-            case 0x101: /* HDHR-US */
-            case 0x102: /* HDHR-T1-US */
-            case 0x103: /* HDHR3-US */
-            case 0x111: /* HDHR3-DT */
-            case 0x121: /* HDHR-EU */
-            case 0x122: /* HDHR3-EU */
-                return true;
-            default:
-                return false;
-        }
-    }
-
-    static class HdHomeRunDiscoverDevice {
-        int mIpAddress;
-        int mDeviceType;
-        int mDeviceId;
-        int mTunerCount;
-        String mBaseUrl;
-
-        @Override
-        public boolean equals(Object other) {
-            if (this == other) {
-                return true;
-            } else if (other instanceof HdHomeRunDiscoverDevice) {
-                HdHomeRunDiscoverDevice o = (HdHomeRunDiscoverDevice) other;
-                return mIpAddress == o.mIpAddress
-                        && mDeviceType == o.mDeviceType
-                        && mDeviceId == o.mDeviceId;
-            }
-            return false;
-        }
-
-        @Override
-        public int hashCode() {
-            int result = mIpAddress;
-            result = 31 * result + mDeviceType;
-            result = 31 * result + mDeviceId;
-            return result;
-        }
-    }
-
-    private static class HdHomeRunDiscoverSocket {
-        DatagramSocket mSocket;
-        boolean mDetected;
-        boolean mDiscoverPacketSent;
-        int mLocalIp;
-        int mSubnetMask;
-
-        private HdHomeRunDiscoverSocket(
-                DatagramSocket socket, boolean detected, int localIp, int subnetMask) {
-            mSocket = socket;
-            mDetected = detected;
-            mLocalIp = localIp;
-            mSubnetMask = subnetMask;
-        }
-
-        private boolean send(int targetIp, int deviceType, int deviceId) {
-            byte[] data = new byte[12];
-            ByteBuffer buffer = ByteBuffer.wrap(data);
-            buffer.put(HdHomeRunUtils.HDHOMERUN_TAG_DEVICE_TYPE);
-            buffer.put((byte) 4);
-            buffer.putInt(deviceType);
-            buffer.put(HdHomeRunUtils.HDHOMERUN_TAG_DEVICE_ID);
-            buffer.put((byte) 4);
-            buffer.putInt(deviceId);
-            data = HdHomeRunUtils.sealFrame(data, HdHomeRunUtils.HDHOMERUN_TYPE_DISCOVER_REQUEST);
-            try {
-                DatagramPacket packet =
-                        new DatagramPacket(
-                                data,
-                                data.length,
-                                HdHomeRunUtils.intToAddress(targetIp),
-                                HdHomeRunUtils.HDHOMERUN_DISCOVER_UDP_PORT);
-                mSocket.send(packet);
-                if (DEBUG) {
-                    Log.d(TAG, "Discover packet sent to: " + HdHomeRunUtils.getIpString(targetIp));
-                }
-                mDiscoverPacketSent = true;
-            } catch (IOException e) {
-                if (DEBUG) {
-                    Log.d(
-                            TAG,
-                            "Cannot send discover packet to socket("
-                                    + HdHomeRunUtils.getIpString(mLocalIp)
-                                    + ")");
-                }
-                mDiscoverPacketSent = false;
-            }
-            return mDiscoverPacketSent;
-        }
-
-        private boolean receive(HdHomeRunDiscoverDevice result) {
-            DatagramPacket packet = new DatagramPacket(new byte[3074], 3074);
-            try {
-                mSocket.setSoTimeout(HDHOMERUN_DISCOVER_RECEIVE_WAITE_TIME_MS);
-                mSocket.receive(packet);
-                if (DEBUG) Log.d(TAG, "Received packet, size: " + packet.getLength());
-            } catch (IOException e) {
-                if (DEBUG) {
-                    Log.d(
-                            TAG,
-                            "Cannot receive from socket("
-                                    + HdHomeRunUtils.getIpString(mLocalIp)
-                                    + ")");
-                }
-                return false;
-            }
-
-            Pair<Short, byte[]> data =
-                    HdHomeRunUtils.openFrame(packet.getData(), packet.getLength());
-            if (data == null
-                    || data.first == null
-                    || data.first != HdHomeRunUtils.HDHOMERUN_TYPE_DISCOVER_REPLY) {
-                if (DEBUG) Log.d(TAG, "Ill-formed packet: " + Arrays.toString(packet.getData()));
-                return false;
-            }
-            result.mIpAddress = HdHomeRunUtils.addressToInt(packet.getAddress().getAddress());
-            if (DEBUG) {
-                Log.d(TAG, "Get Device IP: " + HdHomeRunUtils.getIpString(result.mIpAddress));
-            }
-            ByteBuffer buffer = ByteBuffer.wrap(data.second);
-            while (true) {
-                Pair<Byte, byte[]> tagAndValue = HdHomeRunUtils.readTaggedValue(buffer);
-                if (tagAndValue == null) {
-                    break;
-                }
-                switch (tagAndValue.first) {
-                    case HdHomeRunUtils.HDHOMERUN_TAG_DEVICE_TYPE:
-                        if (tagAndValue.second.length != 4) {
-                            break;
-                        }
-                        result.mDeviceType = ByteBuffer.wrap(tagAndValue.second).getInt();
-                        if (DEBUG) Log.d(TAG, "Get Device Type: " + result.mDeviceType);
-                        break;
-                    case HdHomeRunUtils.HDHOMERUN_TAG_DEVICE_ID:
-                        if (tagAndValue.second.length != 4) {
-                            break;
-                        }
-                        result.mDeviceId = ByteBuffer.wrap(tagAndValue.second).getInt();
-                        if (DEBUG) Log.d(TAG, "Get Device ID: " + result.mDeviceId);
-                        break;
-                    case HdHomeRunUtils.HDHOMERUN_TAG_TUNER_COUNT:
-                        if (tagAndValue.second.length != 1) {
-                            break;
-                        }
-                        result.mTunerCount = tagAndValue.second[0];
-                        if (DEBUG) Log.d(TAG, "Get Tuner Count: " + result.mTunerCount);
-                        break;
-                    case HdHomeRunUtils.HDHOMERUN_TAG_BASE_URL:
-                        result.mBaseUrl = new String(tagAndValue.second);
-                        if (DEBUG) Log.d(TAG, "Get Base URL: " + result.mBaseUrl);
-                        break;
-                    default:
-                        break;
-                }
-            }
-            // Fixup for old firmware.
-            if (result.mTunerCount == 0) {
-                switch (result.mDeviceId >> 20) {
-                    case 0x102:
-                        result.mTunerCount = 1;
-                        break;
-                    case 0x100:
-                    case 0x101:
-                    case 0x121:
-                        result.mTunerCount = 2;
-                        break;
-                    default:
-                        break;
-                }
-            }
-            return true;
-        }
-
-        private void close() {
-            if (mSocket != null) {
-                mSocket.close();
-            }
-        }
-    }
-
-    private static class LocalIpInfo {
-        int mIpAddress;
-        int mSubnetMask;
-    }
-}
diff --git a/tuner/src/com/android/tv/tuner/hdhomerun/HdHomeRunInterface.java b/tuner/src/com/android/tv/tuner/hdhomerun/HdHomeRunInterface.java
deleted file mode 100644
index 2928aba..0000000
--- a/tuner/src/com/android/tv/tuner/hdhomerun/HdHomeRunInterface.java
+++ /dev/null
@@ -1,134 +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.tuner.hdhomerun;
-
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.annotation.WorkerThread;
-import android.util.Log;
-import com.android.tv.tuner.hdhomerun.HdHomeRunDiscover.HdHomeRunDiscoverDevice;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/** An interface class provides methods to access physical HDHomeRun devices. */
-@WorkerThread
-public class HdHomeRunInterface {
-    private static final String TAG = "HdHomeRunInterface";
-    private static final boolean DEBUG = false;
-
-    private static final int FETCH_DEVICE_NAME_TRY_NUM = 2;
-    private static final int MAX_DEVICES = 1;
-    private static final boolean DISABLE_CABLE = false;
-
-    /**
-     * Scans for HDHomeRun devices on the network.
-     *
-     * @param deviceId The target device ID we want to find, scans for all available devices if
-     *     {@code null} or the given ID cannot be found.
-     * @return A set of HDHomeRun devices
-     */
-    @NonNull
-    public static Set<HdHomeRunDevice> scanDevices(Integer deviceId) {
-        List<HdHomeRunDiscoverDevice> discoveredDevices = null;
-        if (deviceId != null) {
-            discoveredDevices =
-                    HdHomeRunUtils.findHdHomeRunDevices(
-                            0, HdHomeRunUtils.HDHOMERUN_DEVICE_TYPE_TUNER, deviceId, 1);
-            if (discoveredDevices.isEmpty()) {
-                Log.i(TAG, "Can't find device with ID: " + deviceId);
-            }
-        }
-        if (discoveredDevices == null || discoveredDevices.isEmpty()) {
-            discoveredDevices =
-                    HdHomeRunUtils.findHdHomeRunDevices(
-                            0,
-                            HdHomeRunUtils.HDHOMERUN_DEVICE_TYPE_TUNER,
-                            HdHomeRunUtils.HDHOMERUN_DEVICE_ID_WILDCARD,
-                            MAX_DEVICES);
-            if (DEBUG) Log.d(TAG, "Found " + discoveredDevices.size() + " devices");
-        }
-        Set<HdHomeRunDevice> result = new HashSet<>();
-        for (HdHomeRunDiscoverDevice discoveredDevice : discoveredDevices) {
-            String model =
-                    fetchDeviceModel(discoveredDevice.mDeviceId, discoveredDevice.mIpAddress);
-            if (model == null) {
-                Log.e(TAG, "Fetching device model failed: " + discoveredDevice.mDeviceId);
-                continue;
-            } else if (DEBUG) {
-                Log.d(TAG, "Fetch Device Model: " + model);
-            }
-            if (DISABLE_CABLE) {
-                if (model != null && model.contains("cablecard")) {
-                    // filter out CableCARD devices
-                    continue;
-                }
-            }
-            for (int i = 0; i < discoveredDevice.mTunerCount; i++) {
-                result.add(
-                        new HdHomeRunDevice(
-                                discoveredDevice.mIpAddress,
-                                discoveredDevice.mDeviceType,
-                                discoveredDevice.mDeviceId,
-                                i,
-                                model));
-            }
-        }
-        return result;
-    }
-
-    /**
-     * Returns {@code true} if the given device IP, ID and tuner index is available for use.
-     *
-     * @param deviceId The target device ID, 0 denotes a wildcard match.
-     * @param deviceIp The target device IP.
-     * @param tunerIndex The target tuner index of the target device. This parameter is only
-     *     meaningful when the target device has multiple tuners.
-     */
-    public static boolean isDeviceAvailable(int deviceId, int deviceIp, int tunerIndex) {
-        // TODO: check the lock state for the given tuner.
-        if ((deviceId == 0) && (deviceIp == 0)) {
-            return false;
-        }
-        if (HdHomeRunUtils.isIpMulticast(deviceIp)) {
-            return false;
-        }
-        if ((deviceId == 0) || (deviceId == HdHomeRunUtils.HDHOMERUN_DEVICE_ID_WILDCARD)) {
-            try (HdHomeRunControlSocket controlSock =
-                    new HdHomeRunControlSocket(deviceId, deviceIp)) {
-                deviceId = controlSock.getDeviceId();
-            }
-        }
-        return deviceId != 0;
-    }
-
-    @Nullable
-    private static String fetchDeviceModel(int deviceId, int deviceIp) {
-        for (int i = 0; i < FETCH_DEVICE_NAME_TRY_NUM; i++) {
-            try (HdHomeRunControlSocket controlSock =
-                    new HdHomeRunControlSocket(deviceId, deviceIp)) {
-                String model = controlSock.get("/sys/model");
-                if (model != null) {
-                    return model;
-                }
-            }
-        }
-        return null;
-    }
-
-    private HdHomeRunInterface() {}
-}
diff --git a/tuner/src/com/android/tv/tuner/hdhomerun/HdHomeRunTunerHal.java b/tuner/src/com/android/tv/tuner/hdhomerun/HdHomeRunTunerHal.java
deleted file mode 100644
index 8168299..0000000
--- a/tuner/src/com/android/tv/tuner/hdhomerun/HdHomeRunTunerHal.java
+++ /dev/null
@@ -1,250 +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.tuner.hdhomerun;
-
-import android.content.Context;
-import android.text.TextUtils;
-import android.util.Log;
-import com.android.tv.common.SoftPreconditions;
-import com.android.tv.common.compat.TvInputConstantCompat;
-import com.android.tv.tuner.api.Tuner;
-import com.android.tv.tuner.data.TunerChannel;
-import java.io.BufferedInputStream;
-import java.io.IOException;
-import java.net.HttpURLConnection;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLConnection;
-
-/** Tuner implementation for HdHomeRun */
-public class HdHomeRunTunerHal implements Tuner {
-    private static final String TAG = "HdHomeRunTunerHal";
-    private static final boolean DEBUG = false;
-
-    private static final String CABLECARD_MODEL = "cablecard";
-    private static final String ATSC_MODEL = "atsc";
-    private static final String DVBC_MODEL = "dvbc";
-    private static final String DVBT_MODEL = "dvbt";
-
-    private final HdHomeRunTunerManager mTunerManager;
-    private HdHomeRunDevice mDevice;
-    private BufferedInputStream mInputStream;
-    private HttpURLConnection mConnection;
-    private String mHttpConnectionAddress;
-    private final Context mContext;
-
-    @DeliverySystemType private int mDeliverySystemType = DELIVERY_SYSTEM_UNDEFINED;
-
-    public static final char VCHANNEL_SEPARATOR = '.';
-    public static final int CONNECTION_TIMEOUT_MS_FOR_URLCONNECTION = 3000; // 3 sec
-    public static final int READ_TIMEOUT_MS_FOR_URLCONNECTION = 10000; // 10 sec
-
-    public HdHomeRunTunerHal(Context context) {
-        mTunerManager = HdHomeRunTunerManager.getInstance();
-        mContext = context;
-    }
-
-    @Override
-    public boolean openFirstAvailable() {
-        SoftPreconditions.checkState(mDevice == null);
-        try {
-            mDevice = mTunerManager.acquireDevice(mContext);
-            if (mDevice != null) {
-                if (mDeliverySystemType == DELIVERY_SYSTEM_UNDEFINED) {
-                    mDeliverySystemType = nativeGetDeliverySystemType(getDeviceId());
-                }
-            }
-            return mDevice != null;
-        } catch (Exception e) {
-            Log.w(TAG, "Failed to open first available device", e);
-            return false;
-        }
-    }
-
-    @Override
-    public boolean isDeviceOpen() {
-        return mDevice != null;
-    }
-
-    @Override
-    public boolean isReusable() {
-        return false;
-    }
-
-    @Override
-    public long getDeviceId() {
-        return mDevice == null ? 0 : mDevice.getDeviceId();
-    }
-
-    @Override
-    public void close() throws Exception {
-        closeInputStreamAndDisconnect();
-        if (mDevice != null) {
-            mTunerManager.releaseDevice(mDevice);
-            mDevice = null;
-        }
-    }
-
-    @Override
-    public synchronized boolean tune(
-            int frequency, @ModulationType String modulation, String channelNumber) {
-        if (DEBUG) {
-            Log.d(
-                    TAG,
-                    "tune(frequency="
-                            + frequency
-                            + ", modulation="
-                            + modulation
-                            + ", channelNumber="
-                            + channelNumber
-                            + ")");
-        }
-        closeInputStreamAndDisconnect();
-        if (TextUtils.isEmpty(channelNumber)) {
-            return false;
-        }
-        channelNumber =
-                channelNumber.replace(TunerChannel.CHANNEL_NUMBER_SEPARATOR, VCHANNEL_SEPARATOR);
-        mHttpConnectionAddress = "http://" + getIpAddress() + ":5004/auto/v" + channelNumber;
-        return connectAndOpenInputStream();
-    }
-
-    private boolean connectAndOpenInputStream() {
-        URL url;
-        try {
-            url = new URL(mHttpConnectionAddress);
-        } catch (MalformedURLException e) {
-            Log.e(TAG, "Invalid address: " + mHttpConnectionAddress, e);
-            return false;
-        }
-        URLConnection connection;
-        try {
-            connection = url.openConnection();
-            connection.setConnectTimeout(CONNECTION_TIMEOUT_MS_FOR_URLCONNECTION);
-            connection.setReadTimeout(READ_TIMEOUT_MS_FOR_URLCONNECTION);
-            if (connection instanceof HttpURLConnection) {
-                mConnection = (HttpURLConnection) connection;
-            }
-        } catch (IOException e) {
-            Log.e(TAG, "Connection failed: " + mHttpConnectionAddress, e);
-            return false;
-        }
-        try {
-            mInputStream = new BufferedInputStream(connection.getInputStream());
-        } catch (IOException e) {
-            closeInputStreamAndDisconnect();
-            Log.e(TAG, "Failed to get input stream from " + mHttpConnectionAddress, e);
-            return false;
-        }
-        if (DEBUG) Log.d(TAG, "tuning to " + mHttpConnectionAddress);
-        return true;
-    }
-
-    @Override
-    public synchronized boolean addPidFilter(int pid, @FilterType int filterType) {
-        // no-op
-        return true;
-    }
-
-    @Override
-    public synchronized void stopTune() {
-        closeInputStreamAndDisconnect();
-    }
-
-    @Override
-    public synchronized int readTsStream(byte[] javaBuffer, int javaBufferSize) {
-        if (mInputStream != null) {
-            try {
-                // Note: this call sometimes take more than 500ms, because the data is
-                // streamed through network unlike connected tuner devices.
-                return mInputStream.read(javaBuffer, 0, javaBufferSize);
-            } catch (IOException e) {
-                Log.e(TAG, "Failed to read stream", e);
-                closeInputStreamAndDisconnect();
-            }
-        }
-        if (connectAndOpenInputStream()) {
-            Log.w(TAG, "Tuned by http connection again");
-        } else {
-            Log.e(TAG, "Tuned by http connection again failed");
-        }
-        return 0;
-    }
-
-    @Override
-    public void setHasPendingTune(boolean hasPendingTune) {
-        // no-op
-    }
-
-    protected int nativeGetDeliverySystemType(long deviceId) {
-        String deviceModel = mDevice.getDeviceModel();
-        if (SoftPreconditions.checkState(!TextUtils.isEmpty(deviceModel))) {
-            if (deviceModel.contains(CABLECARD_MODEL) || deviceModel.contains(ATSC_MODEL)) {
-                return DELIVERY_SYSTEM_ATSC;
-            } else if (deviceModel.contains(DVBC_MODEL)) {
-                return DELIVERY_SYSTEM_DVBC;
-            } else if (deviceModel.contains(DVBT_MODEL)) {
-                return DELIVERY_SYSTEM_DVBT;
-            }
-        }
-        return DELIVERY_SYSTEM_UNDEFINED;
-    }
-
-    private void closeInputStreamAndDisconnect() {
-        if (mInputStream != null) {
-            try {
-                mInputStream.close();
-            } catch (IOException e) {
-                Log.e(TAG, "Failed to close input stream", e);
-            }
-            mInputStream = null;
-        }
-        if (mConnection != null) {
-            mConnection.disconnect();
-            mConnection = null;
-        }
-    }
-
-    /** Gets the number of tuners in a given HDHomeRun devices. */
-    public static int getNumberOfDevices() {
-        return HdHomeRunTunerManager.getInstance().getTunerCount();
-    }
-
-    /** Returns the IP address. */
-    public String getIpAddress() {
-        return HdHomeRunUtils.getIpString(mDevice.getIpAddress());
-    }
-
-    /**
-     * Marks the device associated to this instance as a scanned device. Scanned device has higher
-     * priority among multiple HDHomeRun devices.
-     */
-    public void markAsScannedDevice(Context context) {
-        HdHomeRunTunerManager.markAsScannedDevice(context, mDevice);
-    }
-
-    @Override
-    @DeliverySystemType
-    public int getDeliverySystemType() {
-        return Tuner.DELIVERY_SYSTEM_UNDEFINED;
-    }
-
-    @Override
-    public int getSignalStrength() {
-        return TvInputConstantCompat.SIGNAL_STRENGTH_NOT_USED;
-    }
-}
diff --git a/tuner/src/com/android/tv/tuner/hdhomerun/HdHomeRunTunerHalFactory.java b/tuner/src/com/android/tv/tuner/hdhomerun/HdHomeRunTunerHalFactory.java
deleted file mode 100644
index 6f6b186..0000000
--- a/tuner/src/com/android/tv/tuner/hdhomerun/HdHomeRunTunerHalFactory.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2019 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.hdhomerun;
-
-import android.content.Context;
-import android.support.annotation.WorkerThread;
-import android.util.Pair;
-
-import com.android.tv.tuner.api.Tuner;
-import com.android.tv.tuner.api.TunerFactory;
-
-/** TunerHal factory that creates all built in tuner types. */
-public final class HdHomeRunTunerHalFactory implements TunerFactory {
-    public static final TunerFactory INSTANCE = new HdHomeRunTunerHalFactory();
-
-    private HdHomeRunTunerHalFactory() {}
-    /**
-     * Creates a TunerHal instance.
-     *
-     * @param context context for creating the TunerHal instance
-     * @return the TunerHal instance
-     */
-    @Override
-    @WorkerThread
-    public synchronized Tuner createInstance(Context context) {
-        Tuner tunerHal = null;
-        if (tunerHal == null) {
-            tunerHal = new HdHomeRunTunerHal(context);
-        }
-        return tunerHal.openFirstAvailable() ? tunerHal : null;
-    }
-
-    /**
-     * Returns if tuner input service would use built-in tuners instead of USB tuners or network
-     * tuners.
-     */
-    @Override
-    public boolean useBuiltInTuner(Context context) {
-        return false;
-    }
-
-    /** Gets the number of tuner devices currently present. */
-    @Override
-    @WorkerThread
-    public Pair<Integer, Integer> getTunerTypeAndCount(Context context) {
-        return Pair.create(Tuner.TUNER_TYPE_NETWORK, HdHomeRunTunerHal.getNumberOfDevices());
-    }
-}
diff --git a/tuner/src/com/android/tv/tuner/hdhomerun/HdHomeRunTunerManager.java b/tuner/src/com/android/tv/tuner/hdhomerun/HdHomeRunTunerManager.java
deleted file mode 100644
index 9e3ea59..0000000
--- a/tuner/src/com/android/tv/tuner/hdhomerun/HdHomeRunTunerManager.java
+++ /dev/null
@@ -1,122 +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.tuner.hdhomerun;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
-import android.support.annotation.WorkerThread;
-import android.util.Log;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * A class to manage tuner resources of HDHomeRun devices. It handles tuner resource acquisition and
- * release.
- */
-class HdHomeRunTunerManager {
-    private static final String TAG = "HdHomeRunTunerManager";
-    private static final boolean DEBUG = false;
-
-    private static final String PREF_KEY_SCANNED_DEVICE_ID = "scanned_device_id";
-
-    private static HdHomeRunTunerManager sInstance;
-
-    private final Set<HdHomeRunDevice> mHdHomeRunDevices = new HashSet<>();
-    private final Set<HdHomeRunDevice> mUsedDevices = new HashSet<>();
-
-    private HdHomeRunTunerManager() {}
-
-    /** Returns the instance of this manager. */
-    public static synchronized HdHomeRunTunerManager getInstance() {
-        if (sInstance == null) {
-            sInstance = new HdHomeRunTunerManager();
-        }
-        return sInstance;
-    }
-
-    /** Returns number of tuners. */
-    @WorkerThread
-    synchronized int getTunerCount() {
-        updateDevicesLocked(null);
-        if (DEBUG) Log.d(TAG, "getTunerCount: " + mHdHomeRunDevices.size());
-        return mHdHomeRunDevices.size();
-    }
-
-    /** Creates an HDHomeRun device. If there is no available one, returns {@code null}. */
-    @WorkerThread
-    synchronized HdHomeRunDevice acquireDevice(Context context) {
-        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
-        int scannedDeviceId = sp.getInt(PREF_KEY_SCANNED_DEVICE_ID, 0);
-        updateDevicesLocked(scannedDeviceId == 0 ? null : scannedDeviceId);
-        if (DEBUG) Log.d(TAG, "createDevice: device count = " + mHdHomeRunDevices.size());
-        HdHomeRunDevice availableDevice = null;
-        // Use the device used for scanning first since other devices might have different line-up.
-        if (scannedDeviceId != 0) {
-            for (HdHomeRunDevice device : mHdHomeRunDevices) {
-                if (!mUsedDevices.contains(device) && scannedDeviceId == device.getDeviceId()) {
-                    if (!HdHomeRunInterface.isDeviceAvailable(
-                            device.getDeviceId(), device.getIpAddress(), device.getTunerIndex())) {
-                        if (DEBUG) Log.d(TAG, "Device not available: " + device);
-                        continue;
-                    }
-                    availableDevice = device;
-                    break;
-                }
-            }
-        }
-        if (availableDevice == null) {
-            for (HdHomeRunDevice device : mHdHomeRunDevices) {
-                if (!mUsedDevices.contains(device)) {
-                    if (!HdHomeRunInterface.isDeviceAvailable(
-                            device.getDeviceId(), device.getIpAddress(), device.getTunerIndex())) {
-                        if (DEBUG) Log.d(TAG, "Device not available: " + device);
-                        continue;
-                    }
-                    availableDevice = device;
-                    break;
-                }
-            }
-        }
-        if (availableDevice != null) {
-            if (DEBUG) Log.d(TAG, "created device " + availableDevice);
-            mUsedDevices.add(availableDevice);
-            return availableDevice;
-        }
-        return null;
-    }
-
-    /** Releases a created device by {@link #acquireDevice(Context)}. */
-    synchronized void releaseDevice(HdHomeRunDevice device) {
-        if (DEBUG) Log.d(TAG, "releaseDevice: " + device);
-        mUsedDevices.remove(device);
-    }
-
-    /**
-     * Marks the device associated to this instance as a scanned device. Scanned device has higher
-     * priority among multiple HDHomeRun devices.
-     */
-    static void markAsScannedDevice(Context context, HdHomeRunDevice device) {
-        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
-        sp.edit().putInt(PREF_KEY_SCANNED_DEVICE_ID, device.getDeviceId()).apply();
-    }
-
-    private void updateDevicesLocked(Integer deviceId) {
-        mHdHomeRunDevices.clear();
-        mHdHomeRunDevices.addAll(HdHomeRunInterface.scanDevices(deviceId));
-    }
-}
diff --git a/tuner/src/com/android/tv/tuner/hdhomerun/HdHomeRunUtils.java b/tuner/src/com/android/tv/tuner/hdhomerun/HdHomeRunUtils.java
deleted file mode 100644
index 733fc96..0000000
--- a/tuner/src/com/android/tv/tuner/hdhomerun/HdHomeRunUtils.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * 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.hdhomerun;
-
-import android.support.annotation.NonNull;
-import android.util.Log;
-import android.util.Pair;
-
-import com.android.tv.tuner.hdhomerun.HdHomeRunDiscover.HdHomeRunDiscoverDevice;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.nio.BufferUnderflowException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.zip.CRC32;
-
-class HdHomeRunUtils {
-    private static final String TAG = "HdHomeRunUtils";
-    private static final boolean DEBUG = false;
-
-    static final int HDHOMERUN_DEVICE_TYPE_WILDCARD = 0xFFFFFFFF;
-    static final int HDHOMERUN_DEVICE_TYPE_TUNER = 0x00000001;
-    static final int HDHOMERUN_DEVICE_ID_WILDCARD = 0xFFFFFFFF;
-
-    static final int HDHOMERUN_DISCOVER_UDP_PORT = 65001;
-    static final int HDHOMERUN_CONTROL_TCP_PORT = 65001;
-
-    static final short HDHOMERUN_TYPE_INVALID = -1;
-    static final short HDHOMERUN_TYPE_DISCOVER_REQUEST = 0x0002;
-    static final short HDHOMERUN_TYPE_DISCOVER_REPLY = 0x0003;
-    static final short HDHOMERUN_TYPE_GETSET_REQUEST = 0x0004;
-    static final short HDHOMERUN_TYPE_GETSET_REPLY = 0x0005;
-
-    static final byte HDHOMERUN_TAG_DEVICE_TYPE = 0x01;
-    static final byte HDHOMERUN_TAG_DEVICE_ID = 0x02;
-    static final byte HDHOMERUN_TAG_GETSET_NAME = 0x03;
-    static final int HDHOMERUN_TAG_GETSET_VALUE = 0x04;
-    static final int HDHOMERUN_TAG_ERROR_MESSAGE = 0x05;
-    static final int HDHOMERUN_TAG_TUNER_COUNT = 0x10;
-    static final int HDHOMERUN_TAG_BASE_URL = 0x2A;
-
-    static final int HDHOMERUN_CONTROL_CONNECT_TIMEOUT_MS = 2500;
-    static final int HDHOMERUN_CONTROL_SEND_TIMEOUT_MS = 2500;
-    static final int HDHOMERUN_CONTROL_RECEIVE_TIMEOUT_MS = 2500;
-
-    /**
-     * Finds HDHomeRun devices with given IP, type, and ID.
-     *
-     * @param targetIp {@code 0} to find target devices with broadcasting.
-     * @param deviceType The type of target devices.
-     * @param deviceId The ID of target devices.
-     * @param maxCount Maximum number of devices should be returned.
-     */
-    @NonNull
-    static List<HdHomeRunDiscoverDevice> findHdHomeRunDevices(
-            int targetIp, int deviceType, int deviceId, int maxCount) {
-        if (isIpMulticast(targetIp)) {
-            if (DEBUG) Log.d(TAG, "Target IP cannot be multicast IP.");
-            return Collections.emptyList();
-        }
-        try {
-            HdHomeRunDiscover ds = HdHomeRunDiscover.create();
-            if (ds == null) {
-                if (DEBUG) Log.d(TAG, "Cannot create discover object.");
-                return Collections.emptyList();
-            }
-            List<HdHomeRunDiscoverDevice> result =
-                    ds.findDevices(targetIp, deviceType, deviceId, maxCount);
-            ds.close();
-            return result;
-        } catch (Exception e) {
-            Log.w(TAG, "Failed to find HdHomeRun Devices", e);
-            return Collections.emptyList();
-        }
-    }
-
-    /** Returns {@code true} if the given IP is a multi-cast IP. */
-    static boolean isIpMulticast(long ip) {
-        return (ip >= 0xE0000000) && (ip < 0xF0000000);
-    }
-
-    /** Translates a {@code byte[]} address to its integer representation. */
-    static int addressToInt(byte[] address) {
-        return ByteBuffer.wrap(address).order(ByteOrder.LITTLE_ENDIAN).getInt();
-    }
-
-    /** Translates an {@code int} address to a corresponding {@link InetAddress}. */
-    static InetAddress intToAddress(int address) throws UnknownHostException {
-        return InetAddress.getByAddress(
-                ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(address).array());
-    }
-
-    /** Gets {@link String} representation of an {@code int} address. */
-    static String getIpString(int ip) {
-        return String.format(
-                "%d.%d.%d.%d", (ip & 0xff), (ip >> 8 & 0xff), (ip >> 16 & 0xff), (ip >> 24 & 0xff));
-    }
-
-    /**
-     * Opens the packet returned from HDHomeRun devices to acquire the real content and verify it.
-     */
-    static Pair<Short, byte[]> openFrame(byte[] data, int length) {
-        if (length < 4) {
-            return null;
-        }
-        ByteBuffer buffer = ByteBuffer.wrap(data);
-        short resultType = buffer.getShort();
-        int dataLength = buffer.getShort() & 0xffff;
-
-        if (dataLength + 8 > length) {
-            // Not finished yet.
-            return null;
-        }
-        byte[] result = new byte[dataLength];
-        buffer.get(result);
-        byte[] calculatedCrc = getCrcFromBytes(Arrays.copyOfRange(data, 0, dataLength + 4));
-        byte[] packetCrc = new byte[4];
-        buffer.get(packetCrc);
-
-        if (!Arrays.equals(calculatedCrc, packetCrc)) {
-            return Pair.create(HDHOMERUN_TYPE_INVALID, null);
-        }
-
-        return Pair.create(resultType, result);
-    }
-
-    /** Seals the contents in a packet to send to HDHomeRun devices. */
-    static byte[] sealFrame(byte[] data, short frameType) {
-        byte[] result = new byte[data.length + 8];
-        ByteBuffer buffer = ByteBuffer.wrap(result);
-        buffer.putShort(frameType);
-        buffer.putShort((short) data.length);
-        buffer.put(data);
-        buffer.put(getCrcFromBytes(Arrays.copyOfRange(result, 0, data.length + 4)));
-        return result;
-    }
-
-    /** Reads a (tag, value) pair from packets returned from HDHomeRun devices. */
-    static Pair<Byte, byte[]> readTaggedValue(ByteBuffer buffer) {
-        try {
-            Byte tag = buffer.get();
-            byte[] value = readVarLength(buffer);
-            return Pair.create(tag, value);
-        } catch (BufferUnderflowException e) {
-            return null;
-        }
-    }
-
-    private static byte[] readVarLength(ByteBuffer buffer) {
-        short length;
-        Byte lengthByte1 = buffer.get();
-        if ((lengthByte1 & 0x80) != 0) {
-            length = buffer.get();
-            length = (short) ((length << 7) + (lengthByte1 & 0x7F));
-        } else {
-            length = lengthByte1;
-        }
-        byte[] result = new byte[length];
-        buffer.get(result);
-        return result;
-    }
-
-    private static byte[] getCrcFromBytes(byte[] data) {
-        CRC32 crc32 = new CRC32();
-        crc32.update(data);
-        long crc = crc32.getValue();
-        byte[] result = new byte[4];
-        for (int offset = 0; offset < 4; offset++) {
-            result[offset] = (byte) (crc & 0xFF);
-            crc >>= 8;
-        }
-        return result;
-    }
-
-    private HdHomeRunUtils() {}
-}
diff --git a/tuner/src/com/android/tv/tuner/modules/TunerModule.java b/tuner/src/com/android/tv/tuner/modules/TunerModule.java
index ff86e09..4843f38 100644
--- a/tuner/src/com/android/tv/tuner/modules/TunerModule.java
+++ b/tuner/src/com/android/tv/tuner/modules/TunerModule.java
@@ -15,86 +15,9 @@
  */
 package com.android.tv.tuner.modules;
 
-import com.android.tv.tuner.exoplayer.ExoPlayerSampleExtractor;
-import com.android.tv.tuner.exoplayer.ExoPlayerSampleExtractorFactory;
-import com.android.tv.tuner.exoplayer.FileSampleExtractor;
-import com.android.tv.tuner.exoplayer.FileSampleExtractorFactory;
-import com.android.tv.tuner.exoplayer.MpegTsRendererBuilder;
-import com.android.tv.tuner.exoplayer.MpegTsRendererBuilderFactory;
-import com.android.tv.tuner.exoplayer.MpegTsSampleExtractor;
-import com.android.tv.tuner.exoplayer.MpegTsSampleExtractorFactory;
-import com.android.tv.tuner.exoplayer.buffer.RecordingSampleBuffer;
-import com.android.tv.tuner.exoplayer.buffer.RecordingSampleBufferFactory;
-import com.android.tv.tuner.exoplayer.buffer.SampleChunkIoHelper;
-import com.android.tv.tuner.exoplayer.buffer.SampleChunkIoHelperFactory;
 import com.android.tv.tuner.source.TunerSourceModule;
-import com.android.tv.tuner.tvinput.TunerRecordingSessionFactoryImpl;
-import com.android.tv.tuner.tvinput.TunerRecordingSessionWorker;
-import com.android.tv.tuner.tvinput.TunerRecordingSessionWorkerFactory;
-import com.android.tv.tuner.tvinput.TunerSessionExoV2Factory;
-import com.android.tv.tuner.tvinput.TunerSessionV1Factory;
-import com.android.tv.tuner.tvinput.TunerSessionWorker;
-import com.android.tv.tuner.tvinput.TunerSessionWorkerExoV2;
-import com.android.tv.tuner.tvinput.TunerSessionWorkerExoV2Factory;
-import com.android.tv.tuner.tvinput.TunerSessionWorkerFactory;
-import com.android.tv.tuner.tvinput.factory.TunerRecordingSessionFactory;
-import com.android.tv.tuner.tvinput.factory.TunerSessionFactory;
-
-import dagger.Binds;
 import dagger.Module;
-import dagger.Provides;
-
-import com.android.tv.common.flags.TunerFlags;
 
 /** Dagger module for TV Tuners. */
 @Module(includes = {TunerSingletonsModule.class, TunerSourceModule.class})
-public abstract class TunerModule {
-
-    @Provides
-    static TunerSessionFactory tunerSessionFactory(
-            TunerFlags tunerFlags,
-            TunerSessionV1Factory tunerSessionFactory,
-            TunerSessionExoV2Factory tunerSessionExoV2Factory) {
-        return tunerFlags.useExoplayerV2() ? tunerSessionExoV2Factory : tunerSessionFactory;
-    }
-
-    @Binds
-    abstract TunerRecordingSessionWorker.Factory tunerRecordingSessionWorkerFactory(
-            TunerRecordingSessionWorkerFactory tunerRecordingSessionWorkerFactory);
-
-    @Binds
-    abstract TunerSessionWorker.Factory tunerSessionWorkerFactory(
-            TunerSessionWorkerFactory tunerSessionWorkerFactory);
-
-    @Binds
-    abstract TunerSessionWorkerExoV2.Factory tunerSessionWorkerExoV2Factory(
-            TunerSessionWorkerExoV2Factory tunerSessionWorkerExoV2Factory);
-
-    @Binds
-    abstract TunerRecordingSessionFactory tunerRecordingSessionFactory(
-            TunerRecordingSessionFactoryImpl impl);
-
-    @Binds
-    abstract MpegTsRendererBuilder.Factory mpegTsRendererBuilderFactory(
-            MpegTsRendererBuilderFactory mpegTsRendererBuilderFactory);
-
-    @Binds
-    abstract MpegTsSampleExtractor.Factory mpegTsSampleExtractorFactory(
-            MpegTsSampleExtractorFactory mpegTsSampleExtractorFactory);
-
-    @Binds
-    abstract FileSampleExtractor.Factory fileSampleExtractorFactory(
-            FileSampleExtractorFactory fileSampleExtractorFactory);
-
-    @Binds
-    abstract RecordingSampleBuffer.Factory recordingSampleBufferFactory(
-            RecordingSampleBufferFactory recordingSampleBufferFactory);
-
-    @Binds
-    abstract ExoPlayerSampleExtractor.Factory exoPlayerSampleExtractorFactory(
-            ExoPlayerSampleExtractorFactory exoPlayerSampleExtractorFactory);
-
-    @Binds
-    abstract SampleChunkIoHelper.Factory sampleChunkIoHelperFactory(
-            SampleChunkIoHelperFactory sampleChunkIoHelperFactory);
-}
+public class TunerModule {}
diff --git a/tuner/src/com/android/tv/tuner/setup/BaseTunerSetupActivity.java b/tuner/src/com/android/tv/tuner/setup/BaseTunerSetupActivity.java
index 0502690..44f689b 100644
--- a/tuner/src/com/android/tv/tuner/setup/BaseTunerSetupActivity.java
+++ b/tuner/src/com/android/tv/tuner/setup/BaseTunerSetupActivity.java
@@ -75,14 +75,11 @@
         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
-        /* these two resource files are obsolete and removed, so comment them out
-        R.raw.ut_euro_all,
-        R.raw.ut_euro_all */
     };
 
-    protected final String mInputId;
-
     protected ScanFragment mLastScanFragment;
     protected Integer mTunerType;
     protected boolean mNeedToShowPostalCodeFragment;
@@ -93,10 +90,6 @@
 
     private TunerHalCreator mTunerHalCreator;
 
-    protected BaseTunerSetupActivity(String mInputId) {
-        this.mInputId = mInputId;
-    }
-
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         if (DEBUG) {
@@ -229,7 +222,6 @@
                 args1.putInt(
                         ScanFragment.EXTRA_FOR_CHANNEL_SCAN_FILE, CHANNEL_MAP_SCAN_FILE[actionId]);
                 args1.putInt(KEY_TUNER_TYPE, mTunerType);
-                args1.putString(ScanFragment.EXTRA_FOR_INPUT_ID, mInputId);
                 mLastScanFragment.setArguments(args1);
                 showFragment(mLastScanFragment, true);
                 return true;
diff --git a/tuner/src/com/android/tv/tuner/setup/ChannelScanFileParser.java b/tuner/src/com/android/tv/tuner/setup/ChannelScanFileParser.java
index 2e78270..43c584e 100644
--- a/tuner/src/com/android/tv/tuner/setup/ChannelScanFileParser.java
+++ b/tuner/src/com/android/tv/tuner/setup/ChannelScanFileParser.java
@@ -56,7 +56,6 @@
                 }
                 scanChannelList.add(
                         ScanChannel.forTuner(
-                                tokens[0],
                                 Integer.parseInt(tokens[1]),
                                 tokens[2],
                                 tokens.length == 4 ? Integer.parseInt(tokens[3]) : null));
diff --git a/tuner/src/com/android/tv/tuner/setup/ConnectionTypeFragment.java b/tuner/src/com/android/tv/tuner/setup/ConnectionTypeFragment.java
index db29742..ebe4e41 100644
--- a/tuner/src/com/android/tv/tuner/setup/ConnectionTypeFragment.java
+++ b/tuner/src/com/android/tv/tuner/setup/ConnectionTypeFragment.java
@@ -18,12 +18,14 @@
 
 import android.os.Bundle;
 import android.support.annotation.NonNull;
-import androidx.leanback.widget.GuidanceStylist.Guidance;
-import androidx.leanback.widget.GuidedAction;
+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;
 import java.util.List;
+import java.util.TimeZone;
 
 /** A fragment for connection type selection. */
 public class ConnectionTypeFragment extends SetupMultiPaneFragment {
@@ -65,6 +67,7 @@
 
     /** The content fragment of {@link ConnectionTypeFragment}. */
     public static class ContentFragment extends SetupGuidedStepFragment {
+
         @NonNull
         @Override
         public Guidance onCreateGuidance(Bundle savedInstanceState) {
diff --git a/tuner/src/com/android/tv/tuner/setup/LineupFragment.java b/tuner/src/com/android/tv/tuner/setup/LineupFragment.java
index 224237d..41f755d 100644
--- a/tuner/src/com/android/tv/tuner/setup/LineupFragment.java
+++ b/tuner/src/com/android/tv/tuner/setup/LineupFragment.java
@@ -20,8 +20,8 @@
 import android.os.Bundle;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
-import androidx.leanback.widget.GuidanceStylist.Guidance;
-import androidx.leanback.widget.GuidedAction;
+import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
+import android.support.v17.leanback.widget.GuidedAction;
 import android.util.Log;
 import android.view.View;
 import com.android.tv.common.ui.setup.SetupGuidedStepFragment;
diff --git a/tuner/src/com/android/tv/tuner/setup/LiveTvTunerSetupActivity.java b/tuner/src/com/android/tv/tuner/setup/LiveTvTunerSetupActivity.java
new file mode 100644
index 0000000..741edc7
--- /dev/null
+++ b/tuner/src/com/android/tv/tuner/setup/LiveTvTunerSetupActivity.java
@@ -0,0 +1,119 @@
+/*
+ * 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.tuner.setup;
+
+import android.app.FragmentManager;
+import android.content.pm.PackageManager;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.view.KeyEvent;
+import com.android.tv.common.util.PostalCodeUtils;
+import dagger.android.ContributesAndroidInjector;
+
+/** An activity that serves tuner setup process. */
+public class LiveTvTunerSetupActivity extends BaseTunerSetupActivity {
+    private static final String TAG = "LiveTvTunerSetupActivity";
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        // TODO(shubang): use LocationFragment
+        if (checkSelfPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION)
+                != PackageManager.PERMISSION_GRANTED) {
+            // No need to check the request result.
+            requestPermissions(
+                    new String[] {android.Manifest.permission.ACCESS_COARSE_LOCATION},
+                    PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION);
+        }
+    }
+
+    @Override
+    protected void executeGetTunerTypeAndCountAsyncTask() {
+        new AsyncTask<Void, Void, Integer>() {
+            @Override
+            protected Integer doInBackground(Void... arg0) {
+                return mTunerFactory.getTunerTypeAndCount(LiveTvTunerSetupActivity.this).first;
+            }
+
+            @Override
+            protected void onPostExecute(Integer result) {
+                if (!LiveTvTunerSetupActivity.this.isDestroyed()) {
+                    mTunerType = result;
+                    if (result == null) {
+                        finish();
+                    } else if (!mActivityStopped) {
+                        showInitialFragment();
+                    } else {
+                        mPendingShowInitialFragment = true;
+                    }
+                }
+            }
+        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+    }
+
+    @Override
+    public boolean onKeyUp(int keyCode, KeyEvent event) {
+        if (keyCode == KeyEvent.KEYCODE_BACK) {
+            FragmentManager manager = getFragmentManager();
+            int count = manager.getBackStackEntryCount();
+            if (count > 0) {
+                String lastTag = manager.getBackStackEntryAt(count - 1).getName();
+                if (ScanResultFragment.class.getCanonicalName().equals(lastTag) && count >= 2) {
+                    String secondLastTag = manager.getBackStackEntryAt(count - 2).getName();
+                    if (ScanFragment.class.getCanonicalName().equals(secondLastTag)) {
+                        // Pops fragment including ScanFragment.
+                        manager.popBackStack(
+                                secondLastTag, FragmentManager.POP_BACK_STACK_INCLUSIVE);
+                        return true;
+                    }
+                } else if (ScanFragment.class.getCanonicalName().equals(lastTag)) {
+                    mLastScanFragment.finishScan(true);
+                    return true;
+                }
+            }
+        }
+        return super.onKeyUp(keyCode, event);
+    }
+
+    @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) {
+                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
+                }
+            }
+        }
+    }
+
+    /**
+     * Exports {@link LiveTvTunerSetupActivity} for Dagger codegen to create the appropriate
+     * injector.
+     */
+    @dagger.Module
+    public abstract static class Module {
+        @ContributesAndroidInjector
+        abstract LiveTvTunerSetupActivity contributeLiveTvTunerSetupActivityInjector();
+    }
+}
diff --git a/tuner/src/com/android/tv/tuner/setup/LocationFragment.java b/tuner/src/com/android/tv/tuner/setup/LocationFragment.java
index f950405..1234ae2 100644
--- a/tuner/src/com/android/tv/tuner/setup/LocationFragment.java
+++ b/tuner/src/com/android/tv/tuner/setup/LocationFragment.java
@@ -23,14 +23,16 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.support.annotation.NonNull;
+import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
+import android.support.v17.leanback.widget.GuidedAction;
 import android.util.Log;
-import androidx.leanback.widget.GuidanceStylist.Guidance;
-import androidx.leanback.widget.GuidedAction;
+
 import com.android.tv.common.ui.setup.SetupActionHelper;
 import com.android.tv.common.ui.setup.SetupGuidedStepFragment;
 import com.android.tv.common.ui.setup.SetupMultiPaneFragment;
 import com.android.tv.common.util.LocationUtils;
 import com.android.tv.tuner.R;
+
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
@@ -38,7 +40,7 @@
 /** A fragment shows the rationale of location permission */
 public class LocationFragment extends SetupMultiPaneFragment {
     private static final String TAG = "com.android.tv.tuner.setup.LocationFragment";
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = true;
 
     public static final String ACTION_CATEGORY = "com.android.tv.tuner.setup.LocationFragment";
     public static final String KEY_POSTAL_CODE = "key_postal_code";
@@ -77,7 +79,8 @@
                 () -> {
                     synchronized (mPostalCodeLock) {
                         if (DEBUG) {
-                            Log.d(TAG, "get location timeout. mPostalCode=" + mPostalCode);
+                            Log.d(TAG,
+                                    "get location timeout. mPostalCode=" + mPostalCode);
                         }
                         if (mPostalCode == null) {
                             // timeout. setup activity will get null postal code
@@ -118,7 +121,8 @@
                             .id(ACTION_GETTING_LOCATION)
                             .title(getString(R.string.location_choices_getting_location))
                             .focusable(false)
-                            .build());
+                            .build()
+            );
         }
 
         @Override
@@ -143,8 +147,8 @@
         }
 
         @Override
-        public void onRequestPermissionsResult(
-                int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+        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) {
diff --git a/tuner/src/com/android/tv/tuner/setup/PostalCodeFragment.java b/tuner/src/com/android/tv/tuner/setup/PostalCodeFragment.java
index f9ea167..5224797 100644
--- a/tuner/src/com/android/tv/tuner/setup/PostalCodeFragment.java
+++ b/tuner/src/com/android/tv/tuner/setup/PostalCodeFragment.java
@@ -18,9 +18,9 @@
 
 import android.os.Bundle;
 import android.support.annotation.NonNull;
-import androidx.leanback.widget.GuidanceStylist.Guidance;
-import androidx.leanback.widget.GuidedAction;
-import androidx.leanback.widget.GuidedActionsStylist;
+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;
diff --git a/tuner/src/com/android/tv/tuner/setup/ScanFragment.java b/tuner/src/com/android/tv/tuner/setup/ScanFragment.java
index 87a79e3..7d59284 100644
--- a/tuner/src/com/android/tv/tuner/setup/ScanFragment.java
+++ b/tuner/src/com/android/tv/tuner/setup/ScanFragment.java
@@ -40,9 +40,11 @@
 import com.android.tv.tuner.R;
 import com.android.tv.tuner.api.ScanChannel;
 import com.android.tv.tuner.api.Tuner;
-import com.android.tv.tuner.data.Channel.TunerType;
 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.prefs.TunerPreferences;
 import com.android.tv.tuner.source.FileTsStreamer;
 import com.android.tv.tuner.source.TsDataSource;
@@ -72,13 +74,7 @@
     public static final int ACTION_FINISH = 2;
 
     public static final String EXTRA_FOR_CHANNEL_SCAN_FILE = "scan_file_choice";
-    public static final String EXTRA_FOR_INPUT_ID = "input_id";
     public static final String KEY_CHANNEL_NUMBERS = "channel_numbers";
-
-    // Allows adding audio-only channels (CJ music channel) for which VCT is not present.
-    private static final boolean ADD_CJ_MUSIC_CHANNELS = false;
-    private static final int CJ_MUSIC_CHANNEL_FREQUENCY = 585000000;
-
     private static final long CHANNEL_SCAN_SHOW_DELAY_MS = 10000;
     private static final long CHANNEL_SCAN_PERIOD_MS = 4000;
     private static final long SHOW_PROGRESS_DIALOG_DELAY_MS = 300;
@@ -103,6 +99,8 @@
         if (DEBUG) Log.d(TAG, "onCreateView");
         View view = super.onCreateView(inflater, container, savedInstanceState);
         mChannelNumbers = new ArrayList<>();
+        mChannelDataManager = new ChannelDataManager(getActivity().getApplicationContext());
+        mChannelDataManager.checkDataVersion(getActivity());
         mAdapter = new ChannelAdapter();
         mProgressBar = (ProgressBar) view.findViewById(R.id.tune_progress);
         mScanningMessage = (TextView) view.findViewById(R.id.tune_description);
@@ -124,6 +122,8 @@
                 });
         Bundle args = getArguments();
         int tunerType = (args == null ? 0 : args.getInt(BaseTunerSetupActivity.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);
         switch (tunerType) {
             case Tuner.TUNER_TYPE_USB:
@@ -139,28 +139,6 @@
     }
 
     @Override
-    public void onStart() {
-        super.onStart();
-        Bundle args = getArguments();
-        String inputId = args == null ? null : args.getString(ScanFragment.EXTRA_FOR_INPUT_ID);
-        if (inputId == null) {
-            Log.w(TAG, "No input ID, stopping setup activity.");
-            getActivity().finish();
-        }
-
-        mChannelDataManager = new ChannelDataManager(getContext().getApplicationContext(), inputId);
-        mChannelDataManager.checkDataVersion(getActivity());
-    }
-
-    @Override
-    public void onStop() {
-        if (mChannelDataManager != null) {
-            mChannelDataManager.release();
-        }
-        super.onStop();
-    }
-
-    @Override
     protected int getLayoutResourceId() {
         return R.layout.ut_channel_scan;
     }
@@ -176,13 +154,6 @@
     }
 
     @Override
-    public void onResume() {
-        Bundle args = getArguments();
-        startScan(args == null ? 0 : args.getInt(EXTRA_FOR_CHANNEL_SCAN_FILE, 0));
-        super.onResume();
-    }
-
-    @Override
     public void onPause() {
         Log.d(TAG, "onPause");
         if (mChannelScanTask != null) {
@@ -279,7 +250,6 @@
 
         private final Activity mActivity;
         private final int mChannelMapId;
-// AOSP_Comment_Out         private final com.android.tv.tuner.hdhomerun.HdHomeRunTunerHal mNetworkTuner;
         private final TsStreamer mScanTsStreamer;
         private final TsStreamer mFileTsStreamer;
         private final ConditionVariable mConditionStopped;
@@ -300,13 +270,6 @@
                 if (hal == null) {
                     throw new RuntimeException("Failed to open a DVB device");
                 }
-                /* Begin_AOSP_Comment_Out
-                if (hal instanceof com.android.tv.tuner.hdhomerun.HdHomeRunTunerHal) {
-                    mNetworkTuner = (com.android.tv.tuner.hdhomerun.HdHomeRunTunerHal) hal;
-                } else {
-                    mNetworkTuner = null;
-                }
-                End_AOSP_Comment_Out */
                 mScanTsStreamer = new TunerTsStreamer(hal, this);
             }
             mFileTsStreamer = SCAN_LOCAL_STREAMS ? new FileTsStreamer(this, mActivity) : null;
@@ -351,18 +314,6 @@
 
         @Override
         protected Void doInBackground(Void... params) {
-            /* Begin_AOSP_Comment_Out
-            if (mNetworkTuner != null) {
-                mChannelDataManager.notifyScanStarted();
-                com.android.tv.tuner.hdhomerun.HdHomeRunChannelScan hdHomeRunChannelScan =
-                        new com.android.tv.tuner.hdhomerun.HdHomeRunChannelScan(
-                                mActivity.getApplicationContext(), this, mNetworkTuner);
-                hdHomeRunChannelScan.scan(mConditionStopped);
-                mChannelDataManager.notifyScanCompleted();
-                publishProgress(MAX_PROGRESS);
-                return null;
-            }
-            End_AOSP_Comment_Out */
             mScanChannelList.clear();
             if (SCAN_LOCAL_STREAMS) {
                 FileTsStreamer.addLocalStreamFiles(mScanChannelList);
@@ -425,10 +376,6 @@
                                 e);
                     }
                     streamer.stopStream();
-
-                    if (ADD_CJ_MUSIC_CHANNELS) {
-                        addCjMusicChannel(frequency, modulation);
-                    }
                     addChannelsWithoutVct(scanChannel);
                     if (System.currentTimeMillis() > startMs + CHANNEL_SCAN_SHOW_DELAY_MS
                             && !mChannelListVisible) {
@@ -447,24 +394,6 @@
             if (DEBUG) Log.i(TAG, "Channel scan ended");
         }
 
-        private void addCjMusicChannel(int frequency, String modulation) {
-            if (frequency == CJ_MUSIC_CHANNEL_FREQUENCY
-                    && mChannelMapId == R.raw.ut_kr_dev_cj_cable_center_frequencies_qam256) {
-                List<TunerChannel> incompleteChannels =
-                        mScanTsStreamer instanceof TunerTsStreamer
-                                ? ((TunerTsStreamer) mScanTsStreamer).getMalFormedChannels()
-                                : new ArrayList<>();
-                for (TunerChannel tunerChannel : incompleteChannels) {
-                    if ((tunerChannel.getVideoPid() == TunerChannel.INVALID_PID)
-                            && (tunerChannel.getAudioPid() != TunerChannel.INVALID_PID)) {
-                        tunerChannel.setFrequency(frequency);
-                        tunerChannel.setModulation(modulation);
-                        onChannelDetected(tunerChannel, true);
-                    }
-                }
-            }
-        }
-
         private void addChannelsWithoutVct(ScanChannel scanChannel) {
             if (scanChannel.radioFrequencyNumber == null
                     || !(mScanTsStreamer instanceof TunerTsStreamer)) {
@@ -474,7 +403,6 @@
                     ((TunerTsStreamer) mScanTsStreamer).getMalFormedChannels()) {
                 if ((tunerChannel.getVideoPid() != TunerChannel.INVALID_PID)
                         && (tunerChannel.getAudioPid() != TunerChannel.INVALID_PID)) {
-                    tunerChannel.setDeliverySystemType(scanChannel.deliverySystemType);
                     tunerChannel.setFrequency(scanChannel.frequency);
                     tunerChannel.setModulation(scanChannel.modulation);
                     tunerChannel.setShortName(
@@ -492,9 +420,9 @@
 
         private TsStreamer getStreamer(int type) {
             switch (type) {
-                case TunerType.TYPE_TUNER_VALUE:
+                case Channel.TunerType.TYPE_TUNER:
                     return mScanTsStreamer;
-                case TunerType.TYPE_FILE_VALUE:
+                case Channel.TunerType.TYPE_FILE:
                     return mFileTsStreamer;
                 default:
                     return null;
diff --git a/tuner/src/com/android/tv/tuner/setup/ScanResultFragment.java b/tuner/src/com/android/tv/tuner/setup/ScanResultFragment.java
index 01bcc9f..bd3f9ad 100644
--- a/tuner/src/com/android/tv/tuner/setup/ScanResultFragment.java
+++ b/tuner/src/com/android/tv/tuner/setup/ScanResultFragment.java
@@ -20,8 +20,8 @@
 import android.content.res.Resources;
 import android.os.Bundle;
 import android.support.annotation.NonNull;
-import androidx.leanback.widget.GuidanceStylist.Guidance;
-import androidx.leanback.widget.GuidedAction;
+import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
+import android.support.v17.leanback.widget.GuidedAction;
 import com.android.tv.common.ui.setup.SetupGuidedStepFragment;
 import com.android.tv.common.ui.setup.SetupMultiPaneFragment;
 import com.android.tv.tuner.R;
diff --git a/tuner/src/com/android/tv/tuner/setup/WelcomeFragment.java b/tuner/src/com/android/tv/tuner/setup/WelcomeFragment.java
index dfa994b..2a414df 100644
--- a/tuner/src/com/android/tv/tuner/setup/WelcomeFragment.java
+++ b/tuner/src/com/android/tv/tuner/setup/WelcomeFragment.java
@@ -19,8 +19,8 @@
 import android.os.Bundle;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
-import androidx.leanback.widget.GuidanceStylist.Guidance;
-import androidx.leanback.widget.GuidedAction;
+import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
+import android.support.v17.leanback.widget.GuidedAction;
 import com.android.tv.common.ui.setup.SetupGuidedStepFragment;
 import com.android.tv.common.ui.setup.SetupMultiPaneFragment;
 import com.android.tv.tuner.R;
diff --git a/tuner/src/com/android/tv/tuner/singletons/TunerSingletons.java b/tuner/src/com/android/tv/tuner/singletons/TunerSingletons.java
index dfe9005..48b17dc 100644
--- a/tuner/src/com/android/tv/tuner/singletons/TunerSingletons.java
+++ b/tuner/src/com/android/tv/tuner/singletons/TunerSingletons.java
@@ -18,17 +18,4 @@
 import com.android.tv.common.singletons.HasTvInputId;
 
 /** Singletons used in tuner applications */
-public interface TunerSingletons extends HasTvInputId {
-
-    /*
-     * Do not add any new methods here.
-     *
-     * To move a getter to Injection.
-     *  1. Make a type injectable @Singleton.
-     *  2. Mark the getter here as deprecated.
-     *  3. Lazily inject the object in TvApplication.
-     *  4. Move easy usages of getters to injection instead.
-     *  5. Delete the method when all usages are migrated.
-     */
-
-}
+public interface TunerSingletons extends HasTvInputId {}
diff --git a/tuner/src/com/android/tv/tuner/source/FileSourceEventDetector.java b/tuner/src/com/android/tv/tuner/source/FileSourceEventDetector.java
index 5ee897b..85932c8 100644
--- a/tuner/src/com/android/tv/tuner/source/FileSourceEventDetector.java
+++ b/tuner/src/com/android/tv/tuner/source/FileSourceEventDetector.java
@@ -24,9 +24,9 @@
 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.Track.AtscAudioTrack;
-import com.android.tv.tuner.data.Track.AtscCaptionTrack;
 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.ts.EventDetector.EventListener;
 import com.android.tv.tuner.ts.TsParser;
 import java.util.ArrayList;
diff --git a/tuner/src/com/android/tv/tuner/source/FileTsStreamer.java b/tuner/src/com/android/tv/tuner/source/FileTsStreamer.java
index 15f3458..99d37e3 100644
--- a/tuner/src/com/android/tv/tuner/source/FileTsStreamer.java
+++ b/tuner/src/com/android/tv/tuner/source/FileTsStreamer.java
@@ -17,9 +17,7 @@
 package com.android.tv.tuner.source;
 
 import android.content.Context;
-import android.net.Uri;
 import android.os.Environment;
-import android.support.annotation.Nullable;
 import android.util.Log;
 import android.util.SparseBooleanArray;
 import com.android.tv.common.SoftPreconditions;
@@ -28,8 +26,8 @@
 import com.android.tv.tuner.features.TunerFeatures;
 import com.android.tv.tuner.ts.EventDetector.EventListener;
 import com.android.tv.tuner.ts.TsParser;
-import com.google.android.exoplayer2.upstream.DataSpec;
-import com.google.android.exoplayer2.upstream.TransferListener;
+import com.google.android.exoplayer.C;
+import com.google.android.exoplayer.upstream.DataSpec;
 import java.io.BufferedInputStream;
 import java.io.File;
 import java.io.FileInputStream;
@@ -73,7 +71,6 @@
     public static class FileDataSource extends TsDataSource {
         private final FileTsStreamer mTsStreamer;
         private final AtomicLong mLastReadPosition = new AtomicLong(0);
-        private Uri mUri;
         private long mStartBufferedPosition;
 
         private FileDataSource(FileTsStreamer tsStreamer) {
@@ -99,10 +96,9 @@
         }
 
         @Override
-        public long open(DataSpec dataSpec) {
-            mUri = dataSpec.uri;
+        public long open(DataSpec dataSpec) throws IOException {
             mLastReadPosition.set(0);
-            return com.google.android.exoplayer2.C.LENGTH_UNSET;
+            return C.LENGTH_UNBOUNDED;
         }
 
         @Override
@@ -121,19 +117,6 @@
             }
             return ret;
         }
-
-        // ExoPlayer V2 DataSource implementation.
-
-        @Override
-        public void addTransferListener(TransferListener transferListener) {
-            // TODO: Implement to support metrics collection.
-        }
-
-        @Nullable
-        @Override
-        public Uri getUri() {
-            return mUri;
-        }
     }
 
     /**
diff --git a/tuner/src/com/android/tv/tuner/source/TsDataSource.java b/tuner/src/com/android/tv/tuner/source/TsDataSource.java
index 18f4458..cf3c25d 100644
--- a/tuner/src/com/android/tv/tuner/source/TsDataSource.java
+++ b/tuner/src/com/android/tv/tuner/source/TsDataSource.java
@@ -17,7 +17,7 @@
 package com.android.tv.tuner.source;
 
 import com.android.tv.common.compat.TvInputConstantCompat;
-import com.google.android.exoplayer2.upstream.DataSource;
+import com.google.android.exoplayer.upstream.DataSource;
 
 /** {@link DataSource} for MPEG-TS stream, which will be used by {@link TsExtractor}. */
 public abstract class TsDataSource implements DataSource {
diff --git a/tuner/src/com/android/tv/tuner/source/TsDataSourceManager.java b/tuner/src/com/android/tv/tuner/source/TsDataSourceManager.java
index 3c00b5c..28756a9 100644
--- a/tuner/src/com/android/tv/tuner/source/TsDataSourceManager.java
+++ b/tuner/src/com/android/tv/tuner/source/TsDataSourceManager.java
@@ -19,8 +19,8 @@
 import android.content.Context;
 import android.support.annotation.VisibleForTesting;
 import com.android.tv.tuner.api.Tuner;
-import com.android.tv.tuner.data.Channel;
 import com.android.tv.tuner.data.TunerChannel;
+import com.android.tv.tuner.data.nano.Channel;
 import com.android.tv.tuner.ts.EventDetector.EventListener;
 import com.google.auto.factory.AutoFactory;
 import com.google.auto.factory.Provided;
diff --git a/tuner/src/com/android/tv/tuner/source/TunerTsStreamer.java b/tuner/src/com/android/tv/tuner/source/TunerTsStreamer.java
index 19058c8..9e68c91 100644
--- a/tuner/src/com/android/tv/tuner/source/TunerTsStreamer.java
+++ b/tuner/src/com/android/tv/tuner/source/TunerTsStreamer.java
@@ -17,11 +17,8 @@
 package com.android.tv.tuner.source;
 
 import android.content.Context;
-import android.net.Uri;
-import android.support.annotation.Nullable;
 import android.util.Log;
 import android.util.Pair;
-
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.tuner.api.ScanChannel;
 import com.android.tv.tuner.api.Tuner;
@@ -29,10 +26,8 @@
 import com.android.tv.tuner.prefs.TunerPreferences;
 import com.android.tv.tuner.ts.EventDetector;
 import com.android.tv.tuner.ts.EventDetector.EventListener;
-
-import com.google.android.exoplayer2.C;
-import com.google.android.exoplayer2.upstream.DataSpec;
-import com.google.android.exoplayer2.upstream.TransferListener;
+import com.google.android.exoplayer.C;
+import com.google.android.exoplayer.upstream.DataSpec;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
@@ -71,7 +66,6 @@
         private final TunerTsStreamer mTsStreamer;
         private final AtomicLong mLastReadPosition = new AtomicLong(0);
         private long mStartBufferedPosition;
-        private Uri mUri;
 
         private TunerDataSource(TunerTsStreamer tsStreamer) {
             mTsStreamer = tsStreamer;
@@ -96,16 +90,13 @@
         }
 
         @Override
-        public long open(DataSpec dataSpec) {
-            mUri = dataSpec.uri;
+        public long open(DataSpec dataSpec) throws IOException {
             mLastReadPosition.set(0);
-            return C.LENGTH_UNSET;
+            return C.LENGTH_UNBOUNDED;
         }
 
         @Override
-        public void close() {
-            mUri = null;
-        }
+        public void close() {}
 
         @Override
         public int read(byte[] buffer, int offset, int readLength) throws IOException {
@@ -135,18 +126,6 @@
         public int getSignalStrength() {
             return mTsStreamer.getSignalStrength();
         }
-
-        @Override
-        public void addTransferListener(TransferListener transferListener) {
-            // TODO: Implement to support metrics collection.
-        }
-
-        @Nullable
-        @Override
-        public Uri getUri() {
-            return mUri;
-        }
-
     }
     /**
      * Creates {@link TsStreamer} for playing or recording the specified channel.
@@ -173,8 +152,7 @@
     @Override
     public boolean startStream(TunerChannel channel) {
         if (mTunerHal.tune(
-                channel.getDeliverySystemType().getNumber(), channel.getFrequency(),
-                channel.getModulation(), channel.getDisplayNumber(false))) {
+                channel.getFrequency(), channel.getModulation(), channel.getDisplayNumber(false))) {
             if (channel.hasVideo()) {
                 mTunerHal.addPidFilter(channel.getVideoPid(), Tuner.FILTER_TYPE_VIDEO);
             }
@@ -192,7 +170,6 @@
             mTunerHal.addPidFilter(channel.getPcrPid(), Tuner.FILTER_TYPE_PCR);
             if (mEventDetector != null) {
                 mEventDetector.startDetecting(
-                        channel.getDeliverySystemType(),
                         channel.getFrequency(),
                         channel.getModulation(),
                         channel.getProgramNumber());
@@ -222,11 +199,9 @@
 
     @Override
     public boolean startStream(ScanChannel channel) {
-        if (mTunerHal.tune(channel.deliverySystemType.getNumber(), channel.frequency,
-                channel.modulation, null)) {
+        if (mTunerHal.tune(channel.frequency, channel.modulation, null)) {
             mEventDetector.startDetecting(
-                    channel.deliverySystemType, channel.frequency, channel.modulation,
-                    EventDetector.ALL_PROGRAM_NUMBERS);
+                    channel.frequency, channel.modulation, EventDetector.ALL_PROGRAM_NUMBERS);
             synchronized (mCircularBufferMonitor) {
                 if (mStreaming) {
                     Log.w(TAG, "Streaming should be stopped before start streaming");
@@ -320,7 +295,7 @@
     public void registerListener(EventListener listener) {
         if (mEventDetector != null && listener != null) {
             synchronized (mEventListenerActions) {
-                mEventListenerActions.add(Pair.create(listener, true));
+                mEventListenerActions.add(new Pair<>(listener, true));
             }
         }
     }
diff --git a/tuner/src/com/android/tv/tuner/ts/EventDetector.java b/tuner/src/com/android/tv/tuner/ts/EventDetector.java
index 3a2d835..6d1fc27 100644
--- a/tuner/src/com/android/tv/tuner/ts/EventDetector.java
+++ b/tuner/src/com/android/tv/tuner/ts/EventDetector.java
@@ -20,13 +20,12 @@
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
 import com.android.tv.tuner.api.Tuner;
-import com.android.tv.tuner.data.Channel.DeliverySystemType;
 import com.android.tv.tuner.data.PsiData;
 import com.android.tv.tuner.data.PsipData;
 import com.android.tv.tuner.data.PsipData.EitItem;
-import com.android.tv.tuner.data.Track.AtscAudioTrack;
-import com.android.tv.tuner.data.Track.AtscCaptionTrack;
 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;
 import java.util.List;
@@ -52,7 +51,6 @@
     private final SparseBooleanArray mVctCaptionTracksFound = new SparseBooleanArray();
     private final SparseBooleanArray mEitCaptionTracksFound = new SparseBooleanArray();
     private final List<EventListener> mEventListeners = new ArrayList<>();
-    private DeliverySystemType mDeliverySystemType;
     private int mFrequency;
     private String mModulation;
     private int mProgramNumber = ALL_PROGRAM_NUMBERS;
@@ -172,7 +170,6 @@
                     }
                     tunerChannel.setAudioTracks(audioTracks);
                     tunerChannel.setCaptionTracks(captionTracks);
-                    tunerChannel.setDeliverySystemType(mDeliverySystemType);
                     tunerChannel.setFrequency(mFrequency);
                     tunerChannel.setModulation(mModulation);
                     mChannelMap.put(tunerChannel.getProgramNumber(), tunerChannel);
@@ -212,7 +209,6 @@
                     int channelProgramNumber = channel.getServiceId();
                     tunerChannel.setAudioTracks(audioTracks);
                     tunerChannel.setCaptionTracks(captionTracks);
-                    tunerChannel.setDeliverySystemType(mDeliverySystemType);
                     tunerChannel.setFrequency(mFrequency);
                     tunerChannel.setModulation(mModulation);
                     mChannelMap.put(tunerChannel.getProgramNumber(), tunerChannel);
@@ -256,18 +252,10 @@
 
     private void reset() {
         // TODO: Use TsParser.reset()
-        int[] deliverySystemTypes = mTunerHal.getDeliverySystemTypes();
-        boolean isDvbSignal = false;
-        for (int i = 0; i < deliverySystemTypes.length; i++) {
-            if (Tuner.isDvbDeliverySystem(deliverySystemTypes[i])) {
-                isDvbSignal = true;
-                break;
-            }
-        }
         mTsParser =
                 new TsParser(
                         mTsOutputListener,
-                        isDvbSignal);
+                        Tuner.isDvbDeliverySystem(mTunerHal.getDeliverySystemType()));
         mPidSet.clear();
         mVctProgramNumberSet.clear();
         mSdtProgramNumberSet.clear();
@@ -284,10 +272,8 @@
      * @param programNumber The program number if this is for handling tune request. For scanning
      *     purpose, supply {@link #ALL_PROGRAM_NUMBERS}.
      */
-    public void startDetecting(DeliverySystemType deliverySystemType, int frequency,
-                               String modulation, int programNumber) {
+    public void startDetecting(int frequency, String modulation, int programNumber) {
         reset();
-        mDeliverySystemType = deliverySystemType;
         mFrequency = frequency;
         mModulation = modulation;
         mProgramNumber = programNumber;
diff --git a/tuner/src/com/android/tv/tuner/tvinput/BaseTunerTvInputService.java b/tuner/src/com/android/tv/tuner/tvinput/BaseTunerTvInputService.java
index e47162a..d22b639 100644
--- a/tuner/src/com/android/tv/tuner/tvinput/BaseTunerTvInputService.java
+++ b/tuner/src/com/android/tv/tuner/tvinput/BaseTunerTvInputService.java
@@ -21,26 +21,17 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.media.tv.TvInputService;
-import android.net.Uri;
 import android.util.Log;
-
 import com.android.tv.common.feature.CommonFeatures;
+import com.android.tv.tuner.source.TsDataSourceManager;
 import com.android.tv.tuner.tvinput.datamanager.ChannelDataManager;
-import com.android.tv.tuner.tvinput.factory.TunerRecordingSessionFactory;
 import com.android.tv.tuner.tvinput.factory.TunerSessionFactory;
-
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import com.google.common.cache.RemovalListener;
-
 import dagger.android.AndroidInjection;
-
+import com.android.tv.common.flags.ConcurrentDvrPlaybackFlags;
 import java.util.Collections;
 import java.util.Set;
 import java.util.WeakHashMap;
 import java.util.concurrent.TimeUnit;
-
 import javax.inject.Inject;
 
 /** {@link BaseTunerTvInputService} serves TV channels coming from a tuner device. */
@@ -51,19 +42,10 @@
     private static final int DVR_STORAGE_CLEANUP_JOB_ID = 100;
 
     private final Set<Session> mTunerSessions = Collections.newSetFromMap(new WeakHashMap<>());
-    private final Set<RecordingSession> mTunerRecordingSession =
-            Collections.newSetFromMap(new WeakHashMap<>());
+    private ChannelDataManager mChannelDataManager;
+    @Inject ConcurrentDvrPlaybackFlags mConcurrentDvrPlaybackFlags;
+    @Inject TsDataSourceManager.Factory mTsDataSourceManagerFactory;
     @Inject TunerSessionFactory mTunerSessionFactory;
-    @Inject TunerRecordingSessionFactory mTunerRecordingSessionFactory;
-
-    LoadingCache<String, ChannelDataManager> mChannelDataManagers;
-    RemovalListener<String, ChannelDataManager> mChannelDataManagerRemovalListener =
-            notification -> {
-                ChannelDataManager cdm = notification.getValue();
-                if (cdm != null) {
-                    cdm.release();
-                }
-            };
 
     @Override
     public void onCreate() {
@@ -75,17 +57,7 @@
         AndroidInjection.inject(this);
         super.onCreate();
         if (DEBUG) Log.d(TAG, "onCreate");
-        mChannelDataManagers =
-                CacheBuilder.newBuilder()
-                        .weakValues()
-                        .removalListener(mChannelDataManagerRemovalListener)
-                        .build(
-                                new CacheLoader<String, ChannelDataManager>() {
-                                    @Override
-                                    public ChannelDataManager load(String inputId) {
-                                        return createChannelDataManager(inputId);
-                                    }
-                                });
+        mChannelDataManager = new ChannelDataManager(getApplicationContext());
         if (CommonFeatures.DVR.isEnabled(this)) {
             JobScheduler jobScheduler =
                     (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
@@ -105,24 +77,21 @@
         }
     }
 
-    private ChannelDataManager createChannelDataManager(String inputId) {
-        return new ChannelDataManager(getApplicationContext(), inputId);
-    }
-
     @Override
     public void onDestroy() {
         if (DEBUG) Log.d(TAG, "onDestroy");
         super.onDestroy();
-        mChannelDataManagers.invalidateAll();
+        mChannelDataManager.release();
     }
 
     @Override
     public RecordingSession onCreateRecordingSession(String inputId) {
-        RecordingSession session =
-                mTunerRecordingSessionFactory.create(
-                        inputId, this::onReleased, mChannelDataManagers.getUnchecked(inputId));
-        mTunerRecordingSession.add(session);
-        return session;
+        return new TunerRecordingSession(
+                this,
+                inputId,
+                mChannelDataManager,
+                mConcurrentDvrPlaybackFlags,
+                mTsDataSourceManagerFactory);
     }
 
     @Override
@@ -134,12 +103,8 @@
                 Log.d(TAG, "abort creating an session");
                 return null;
             }
-
             final Session session =
-                    mTunerSessionFactory.create(
-                            mChannelDataManagers.getUnchecked(inputId),
-                            this::onReleased,
-                            this::getRecordingUri);
+                    mTunerSessionFactory.create(this, mChannelDataManager, this::onReleased);
             mTunerSessions.add(session);
             session.setOverlayViewEnabled(true);
             return session;
@@ -150,22 +115,7 @@
         }
     }
 
-    private Uri getRecordingUri(Uri channelUri) {
-        for (RecordingSession session : mTunerRecordingSession) {
-            TunerRecordingSession tunerSession = (TunerRecordingSession) session;
-            if (tunerSession.getChannelUri().equals(channelUri)) {
-                return tunerSession.getRecordingUri();
-            }
-        }
-        return null;
-    }
-
     private void onReleased(Session session) {
         mTunerSessions.remove(session);
-        mChannelDataManagers.cleanUp();
-    }
-
-    private void onReleased(RecordingSession session) {
-        mTunerRecordingSession.remove(session);
     }
 }
diff --git a/tuner/src/com/android/tv/tuner/tvinput/TunerRecordingSession.java b/tuner/src/com/android/tv/tuner/tvinput/TunerRecordingSession.java
index ed61f71..5561693 100644
--- a/tuner/src/com/android/tv/tuner/tvinput/TunerRecordingSession.java
+++ b/tuner/src/com/android/tv/tuner/tvinput/TunerRecordingSession.java
@@ -22,40 +22,33 @@
 import android.support.annotation.Nullable;
 import android.support.annotation.WorkerThread;
 import android.util.Log;
-
 import com.android.tv.common.compat.RecordingSessionCompat;
-import com.android.tv.common.dagger.annotations.ApplicationContext;
+import com.android.tv.tuner.source.TsDataSourceManager;
 import com.android.tv.tuner.tvinput.datamanager.ChannelDataManager;
-import com.android.tv.tuner.tvinput.factory.TunerRecordingSessionFactory;
-import com.android.tv.tuner.tvinput.factory.TunerRecordingSessionFactory.RecordingSessionReleasedCallback;
-
-import com.google.auto.factory.AutoFactory;
-import com.google.auto.factory.Provided;
+import com.android.tv.common.flags.ConcurrentDvrPlaybackFlags;
 
 /** Processes DVR recordings, and deletes the previously recorded contents. */
-@AutoFactory(
-        className = "TunerRecordingSessionFactoryImpl",
-        implementing = TunerRecordingSessionFactory.class)
 public class TunerRecordingSession extends RecordingSessionCompat {
     private static final String TAG = "TunerRecordingSession";
     private static final boolean DEBUG = false;
 
     private final TunerRecordingSessionWorker mSessionWorker;
-    private final RecordingSessionReleasedCallback mReleasedCallback;
-    private Uri mChannelUri;
-    private Uri mRecordingUri;
 
     public TunerRecordingSession(
-            @Provided @ApplicationContext Context context,
+            Context context,
             String inputId,
-            RecordingSessionReleasedCallback releasedCallback,
             ChannelDataManager channelDataManager,
-            @Provided TunerRecordingSessionWorker.Factory tunerRecordingSessionWorkerFactory) {
+            ConcurrentDvrPlaybackFlags concurrentDvrPlaybackFlags,
+            TsDataSourceManager.Factory tsDataSourceManagerFactory) {
         super(context);
-        mReleasedCallback = releasedCallback;
         mSessionWorker =
-                tunerRecordingSessionWorkerFactory.create(
-                        context, inputId, channelDataManager, this);
+                new TunerRecordingSessionWorker(
+                        context,
+                        inputId,
+                        channelDataManager,
+                        this,
+                        concurrentDvrPlaybackFlags,
+                        tsDataSourceManagerFactory);
     }
 
     // RecordingSession
@@ -76,7 +69,6 @@
             Log.d(TAG, "Requesting recording session release.");
         }
         mSessionWorker.release();
-        mReleasedCallback.onReleased(this);
     }
 
     @MainThread
@@ -103,7 +95,6 @@
         if (DEBUG) {
             Log.d(TAG, "Notifying recording session tuned.");
         }
-        mChannelUri = channelUri;
         notifyTuned(channelUri);
     }
 
@@ -121,7 +112,6 @@
         if (DEBUG) {
             Log.d(TAG, "Notifying record successfully finished.");
         }
-        mRecordingUri = null;
         notifyRecordingStopped(recordedProgramUri);
     }
 
@@ -130,19 +120,4 @@
         Log.w(TAG, "Notifying recording error: " + reason);
         notifyError(reason);
     }
-
-    public void onRecordingStatePartial(Uri recUri) {
-        if (DEBUG) {
-            Log.d(TAG, "Updating recording session state to Partial");
-        }
-        mRecordingUri = recUri;
-    }
-
-    public Uri getChannelUri() {
-        return mChannelUri;
-    }
-
-    public Uri getRecordingUri() {
-        return mRecordingUri;
-    }
 }
diff --git a/tuner/src/com/android/tv/tuner/tvinput/TunerRecordingSessionWorker.java b/tuner/src/com/android/tv/tuner/tvinput/TunerRecordingSessionWorker.java
index 97cd057..2c0c09a 100644
--- a/tuner/src/com/android/tv/tuner/tvinput/TunerRecordingSessionWorker.java
+++ b/tuner/src/com/android/tv/tuner/tvinput/TunerRecordingSessionWorker.java
@@ -37,19 +37,17 @@
 import android.support.annotation.Nullable;
 import android.util.Log;
 import android.util.Pair;
-
 import androidx.tvprovider.media.tv.Program;
-
 import com.android.tv.common.BaseApplication;
 import com.android.tv.common.data.RecordedProgramState;
 import com.android.tv.common.recording.RecordingCapability;
 import com.android.tv.common.recording.RecordingStorageStatusManager;
 import com.android.tv.common.util.CommonUtils;
+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.Track.AtscCaptionTrack;
 import com.android.tv.tuner.data.TunerChannel;
-import com.android.tv.tuner.dvb.DvbDeviceAccessor;
+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;
@@ -59,11 +57,8 @@
 import com.android.tv.tuner.source.TsDataSourceManager;
 import com.android.tv.tuner.ts.EventDetector.EventListener;
 import com.android.tv.tuner.tvinput.datamanager.ChannelDataManager;
-
 import com.google.android.exoplayer.C;
-import com.google.auto.factory.AutoFactory;
-import com.google.auto.factory.Provided;
-
+import com.android.tv.common.flags.ConcurrentDvrPlaybackFlags;
 import java.io.File;
 import java.io.IOException;
 import java.lang.annotation.Retention;
@@ -147,6 +142,7 @@
 
     private static final long CHANNEL_ID_NONE = -1;
     private static final int MAX_TUNING_RETRY = 6;
+    private final ConcurrentDvrPlaybackFlags mConcurrentDvrPlaybackFlags;
 
     private final Context mContext;
     private final ChannelDataManager mChannelDataManager;
@@ -172,31 +168,15 @@
     private PsipData.EitItem mCurrenProgram;
     private List<AtscCaptionTrack> mCaptionTracks;
     private DvrStorageManager mDvrStorageManager;
-    private final ExoPlayerSampleExtractor.Factory mExoPlayerSampleExtractorFactory;
 
-    /**
-     * Factory for {@link TunerRecordingSessionWorker}}.
-     *
-     * <p>This wrapper class keeps other classes from needing to reference the {@link AutoFactory}
-     * generated class.
-     */
-    public interface Factory {
-        TunerRecordingSessionWorker create(
-                Context context,
-                String inputId,
-                ChannelDataManager dataManager,
-                TunerRecordingSession session);
-    }
-
-    @AutoFactory(implementing = Factory.class)
     public TunerRecordingSessionWorker(
             Context context,
             String inputId,
             ChannelDataManager dataManager,
             TunerRecordingSession session,
-            @Provided ExoPlayerSampleExtractor.Factory exoPlayerSampleExtractorFactory,
-            @Provided TsDataSourceManager.Factory tsDataSourceManagerFactory) {
-        mExoPlayerSampleExtractorFactory = exoPlayerSampleExtractorFactory;
+            ConcurrentDvrPlaybackFlags concurrentDvrPlaybackFlags,
+            TsDataSourceManager.Factory tsDataSourceManagerFactory) {
+        mConcurrentDvrPlaybackFlags = concurrentDvrPlaybackFlags;
         mRandom.setSeed(System.nanoTime());
         mContext = context;
         HandlerThread handlerThread = new HandlerThread(TAG);
@@ -237,7 +217,7 @@
         if (mChannel == null || mChannel.compareTo(channel) != 0) {
             return;
         }
-        mHandler.obtainMessage(MSG_UPDATE_CC_INFO, Pair.create(channel, items)).sendToTarget();
+        mHandler.obtainMessage(MSG_UPDATE_CC_INFO, new Pair<>(channel, items)).sendToTarget();
         mChannelDataManager.notifyEventDetected(channel, items);
     }
 
@@ -382,7 +362,7 @@
                 }
             case MSG_UPDATE_PARTIAL_STATE:
                 {
-                    updateRecordedProgramStatePartial();
+                    updateRecordedProgram(RecordedProgramState.PARTIAL, -1, -1);
                     return true;
                 }
         }
@@ -476,30 +456,36 @@
         mRecordStartTime = System.currentTimeMillis();
         mDvrStorageManager = new DvrStorageManager(mStorageDir, true);
         mRecorder =
-                mExoPlayerSampleExtractorFactory.create(
-                        Uri.EMPTY, mTunerSource, new BufferManager(mDvrStorageManager), this, true);
+                new ExoPlayerSampleExtractor(
+                        Uri.EMPTY,
+                        mTunerSource,
+                        new BufferManager(mDvrStorageManager),
+                        this,
+                        true,
+                        mConcurrentDvrPlaybackFlags);
         mRecorder.setOnCompletionListener(this, mHandler);
         mProgramUri = programUri;
         mSessionState = STATE_RECORDING;
         mRecorderRunning = true;
-        mRecordedProgramUri =
-                insertRecordedProgram(
-                        getRecordedProgram(),
-                        mChannel.getChannelId(),
-                        Uri.fromFile(mStorageDir).toString(),
-                        calculateRecordingSizeInBytes(),
-                        mRecordStartTime,
-                        mRecordStartTime);
-        if (mRecordedProgramUri == null) {
-            new DeleteRecordingTask().execute(mStorageDir);
-            mSession.onError(TvInputManager.RECORDING_ERROR_UNKNOWN);
-            Log.e(TAG, "Inserting a recording to DB failed");
-            return false;
+        if (mConcurrentDvrPlaybackFlags.enabled()) {
+            mRecordedProgramUri =
+                    insertRecordedProgram(
+                            getRecordedProgram(),
+                            mChannel.getChannelId(),
+                            Uri.fromFile(mStorageDir).toString(),
+                            calculateRecordingSizeInBytes(),
+                            mRecordStartTime,
+                            mRecordStartTime);
+            if (mRecordedProgramUri == null) {
+                new DeleteRecordingTask().execute(mStorageDir);
+                mSession.onError(TvInputManager.RECORDING_ERROR_UNKNOWN);
+                Log.e(TAG, "Inserting a recording to DB failed");
+                return false;
+            }
+            mSession.onRecordingUri(mRecordedProgramUri.toString());
+            mHandler.sendEmptyMessageDelayed(
+                    MSG_UPDATE_PARTIAL_STATE, MIN_PARTIAL_RECORDING_DURATION_MS);
         }
-        mSession.onRecordingUri(mRecordedProgramUri.toString());
-        mHandler.sendEmptyMessageDelayed(
-                MSG_UPDATE_PARTIAL_STATE, MIN_PARTIAL_RECORDING_DURATION_MS);
-
         mHandler.sendEmptyMessage(MSG_PREPARE_RECODER);
         mHandler.removeMessages(MSG_MONITOR_STORAGE_STATUS);
         mHandler.sendEmptyMessageDelayed(MSG_MONITOR_STORAGE_STATUS, STORAGE_MONITOR_INTERVAL_MS);
@@ -606,7 +592,7 @@
         if (checkRecordedProgramTable(COLUMN_SERIES_ID)) {
             values.put(COLUMN_SERIES_ID, mSeriesId);
         }
-        if (checkRecordedProgramTable(COLUMN_STATE)) {
+        if (mConcurrentDvrPlaybackFlags.enabled() && checkRecordedProgramTable(COLUMN_STATE)) {
             values.put(COLUMN_STATE, RecordedProgramState.STARTED.name());
         }
         if (program != null) {
@@ -616,26 +602,20 @@
                 .insert(TvContract.RecordedPrograms.CONTENT_URI, values);
     }
 
-    private void updateRecordedProgramStateFinished(long endTime, long totalBytes) {
+    private void updateRecordedProgram(RecordedProgramState state, long endTime, long totalBytes) {
         ContentValues values = new ContentValues();
-        values.put(RecordedPrograms.COLUMN_RECORDING_DATA_BYTES, totalBytes);
-        values.put(RecordedPrograms.COLUMN_RECORDING_DURATION_MILLIS, endTime - mRecordStartTime);
-        values.put(RecordedPrograms.COLUMN_END_TIME_UTC_MILLIS, endTime);
         if (checkRecordedProgramTable(COLUMN_STATE)) {
-            values.put(COLUMN_STATE, RecordedProgramState.FINISHED.name());
+            values.put(COLUMN_STATE, state.name());
+        }
+        if (state.equals(RecordedProgramState.FINISHED)) {
+            values.put(RecordedPrograms.COLUMN_RECORDING_DATA_BYTES, totalBytes);
+            values.put(
+                    RecordedPrograms.COLUMN_RECORDING_DURATION_MILLIS, endTime - mRecordStartTime);
+            values.put(RecordedPrograms.COLUMN_END_TIME_UTC_MILLIS, endTime);
         }
         mContext.getContentResolver().update(mRecordedProgramUri, values, null, null);
     }
 
-    private void updateRecordedProgramStatePartial() {
-        mSession.onRecordingStatePartial(mRecordedProgramUri);
-        if (checkRecordedProgramTable(COLUMN_STATE)) {
-            ContentValues values = new ContentValues();
-            values.put(COLUMN_STATE, RecordedProgramState.PARTIAL.name());
-            mContext.getContentResolver().update(mRecordedProgramUri, values, null, null);
-        }
-    }
-
     private void onRecordingResult(boolean success, long lastExtractedPositionUs) {
         if (mSessionState != STATE_RECORDING) {
             // Error notification is not needed.
@@ -660,7 +640,25 @@
                 (lastExtractedPositionUs == C.UNKNOWN_TIME_US)
                         ? System.currentTimeMillis()
                         : mRecordStartTime + lastExtractedPositionUs / 1000;
-        updateRecordedProgramStateFinished(recordEndTime, calculateRecordingSizeInBytes());
+        if (!mConcurrentDvrPlaybackFlags.enabled()) {
+            mRecordedProgramUri =
+                    insertRecordedProgram(
+                            getRecordedProgram(),
+                            mChannel.getChannelId(),
+                            Uri.fromFile(mStorageDir).toString(),
+                            calculateRecordingSizeInBytes(),
+                            mRecordStartTime,
+                            recordEndTime);
+            if (mRecordedProgramUri == null) {
+                new DeleteRecordingTask().execute(mStorageDir);
+                mSession.onError(TvInputManager.RECORDING_ERROR_UNKNOWN);
+                Log.e(TAG, "Inserting a recording to DB failed");
+                return;
+            }
+        } else {
+            updateRecordedProgram(
+                    RecordedProgramState.FINISHED, recordEndTime, calculateRecordingSizeInBytes());
+        }
         mDvrStorageManager.writeCaptionInfoFiles(mCaptionTracks);
         mSession.onRecordFinished(mRecordedProgramUri);
     }
diff --git a/tuner/src/com/android/tv/tuner/tvinput/TunerSession.java b/tuner/src/com/android/tv/tuner/tvinput/TunerSession.java
index eb3a7d0..fedb5f6 100644
--- a/tuner/src/com/android/tv/tuner/tvinput/TunerSession.java
+++ b/tuner/src/com/android/tv/tuner/tvinput/TunerSession.java
@@ -27,24 +27,18 @@
 import android.util.Log;
 import android.view.Surface;
 import android.view.View;
-
 import com.android.tv.common.CommonPreferences.CommonPreferencesChangedListener;
 import com.android.tv.common.compat.TisSessionCompat;
-import com.android.tv.common.dagger.annotations.ApplicationContext;
 import com.android.tv.tuner.prefs.TunerPreferences;
+import com.android.tv.tuner.source.TsDataSourceManager;
 import com.android.tv.tuner.tvinput.datamanager.ChannelDataManager;
-import com.android.tv.tuner.tvinput.factory.TunerSessionFactory;
-import com.android.tv.tuner.tvinput.factory.TunerSessionFactory.SessionRecordingCallback;
 import com.android.tv.tuner.tvinput.factory.TunerSessionFactory.SessionReleasedCallback;
-
-import com.google.auto.factory.AutoFactory;
-import com.google.auto.factory.Provided;
+import com.android.tv.common.flags.ConcurrentDvrPlaybackFlags;
 
 /**
  * Provides a tuner TV input session. Main tuner input functions are implemented in {@link
  * TunerSessionWorker}.
  */
-@AutoFactory(className = "TunerSessionV1Factory", implementing = TunerSessionFactory.class)
 public class TunerSession extends TisSessionCompat implements CommonPreferencesChangedListener {
 
     private static final String TAG = "TunerSession";
@@ -53,26 +47,26 @@
     private final TunerSessionOverlay mTunerSessionOverlay;
     private final TunerSessionWorker mSessionWorker;
     private final SessionReleasedCallback mReleasedCallback;
-    private final SessionRecordingCallback mRecordingCallback;
     private boolean mPlayPaused;
     private long mTuneStartTimestamp;
 
     public TunerSession(
-            @Provided @ApplicationContext Context context,
+            Context context,
             ChannelDataManager channelDataManager,
             SessionReleasedCallback releasedCallback,
-            SessionRecordingCallback recordingCallback,
-            @Provided TunerSessionWorker.Factory tunerSessionWorkerFactory) {
+            ConcurrentDvrPlaybackFlags concurrentDvrPlaybackFlags,
+            TsDataSourceManager.Factory tsDataSourceManagerFactory) {
         super(context);
         mReleasedCallback = releasedCallback;
-        mRecordingCallback = recordingCallback;
         mTunerSessionOverlay = new TunerSessionOverlay(context);
         mSessionWorker =
-                tunerSessionWorkerFactory.create(
+                new TunerSessionWorker(
                         context,
                         channelDataManager,
                         this,
-                        mTunerSessionOverlay);
+                        mTunerSessionOverlay,
+                        concurrentDvrPlaybackFlags,
+                        tsDataSourceManagerFactory);
         TunerPreferences.setCommonPreferencesChangedListener(this);
     }
 
@@ -210,8 +204,4 @@
     public void onCommonPreferencesChanged() {
         mSessionWorker.sendMessage(TunerSessionWorker.MSG_TUNER_PREFERENCES_CHANGED);
     }
-
-    public Uri getRecordingUri(Uri channelUri) {
-        return mRecordingCallback.getRecordingUri(channelUri);
-    }
 }
diff --git a/tuner/src/com/android/tv/tuner/tvinput/TunerSessionExoV2.java b/tuner/src/com/android/tv/tuner/tvinput/TunerSessionExoV2.java
index 7ebb2b2..4eca44d 100644
--- a/tuner/src/com/android/tv/tuner/tvinput/TunerSessionExoV2.java
+++ b/tuner/src/com/android/tv/tuner/tvinput/TunerSessionExoV2.java
@@ -27,21 +27,15 @@
 import android.util.Log;
 import android.view.Surface;
 import android.view.View;
-
 import com.android.tv.common.CommonPreferences.CommonPreferencesChangedListener;
 import com.android.tv.common.compat.TisSessionCompat;
-import com.android.tv.common.dagger.annotations.ApplicationContext;
 import com.android.tv.tuner.prefs.TunerPreferences;
+import com.android.tv.tuner.source.TsDataSourceManager;
 import com.android.tv.tuner.tvinput.datamanager.ChannelDataManager;
-import com.android.tv.tuner.tvinput.factory.TunerSessionFactory;
-import com.android.tv.tuner.tvinput.factory.TunerSessionFactory.SessionRecordingCallback;
 import com.android.tv.tuner.tvinput.factory.TunerSessionFactory.SessionReleasedCallback;
-
-import com.google.auto.factory.AutoFactory;
-import com.google.auto.factory.Provided;
+import com.android.tv.common.flags.ConcurrentDvrPlaybackFlags;
 
 /** Provides a tuner TV input session. */
-@AutoFactory(implementing = TunerSessionFactory.class)
 public class TunerSessionExoV2 extends TisSessionCompat
         implements CommonPreferencesChangedListener {
 
@@ -51,26 +45,26 @@
     private final TunerSessionOverlay mTunerSessionOverlay;
     private final TunerSessionWorkerExoV2 mSessionWorker;
     private final SessionReleasedCallback mReleasedCallback;
-    private final SessionRecordingCallback mRecordingCallback;
     private boolean mPlayPaused;
     private long mTuneStartTimestamp;
 
     public TunerSessionExoV2(
-            @Provided @ApplicationContext Context context,
+            Context context,
             ChannelDataManager channelDataManager,
             SessionReleasedCallback releasedCallback,
-            SessionRecordingCallback recordingCallback,
-            @Provided TunerSessionWorkerExoV2.Factory tunerSessionWorkerExoV2Factory) {
+            ConcurrentDvrPlaybackFlags concurrentDvrPlaybackFlags,
+            TsDataSourceManager.Factory tsDataSourceManagerFactory) {
         super(context);
         mReleasedCallback = releasedCallback;
-        mRecordingCallback = recordingCallback;
         mTunerSessionOverlay = new TunerSessionOverlay(context);
         mSessionWorker =
-                tunerSessionWorkerExoV2Factory.create(
+                new TunerSessionWorkerExoV2(
                         context,
                         channelDataManager,
                         this,
-                        mTunerSessionOverlay);
+                        mTunerSessionOverlay,
+                        concurrentDvrPlaybackFlags,
+                        tsDataSourceManagerFactory);
         TunerPreferences.setCommonPreferencesChangedListener(this);
     }
 
@@ -209,8 +203,4 @@
     public void onCommonPreferencesChanged() {
         mSessionWorker.sendMessage(TunerSessionWorkerExoV2.MSG_TUNER_PREFERENCES_CHANGED);
     }
-
-    public Uri getRecordingUri(Uri channelUri) {
-        return mRecordingCallback.getRecordingUri(channelUri);
-    }
 }
diff --git a/tuner/src/com/android/tv/tuner/tvinput/TunerSessionOverlay.java b/tuner/src/com/android/tv/tuner/tvinput/TunerSessionOverlay.java
index 53e0bcc..9f21e16 100644
--- a/tuner/src/com/android/tv/tuner/tvinput/TunerSessionOverlay.java
+++ b/tuner/src/com/android/tv/tuner/tvinput/TunerSessionOverlay.java
@@ -26,18 +26,17 @@
 import android.view.ViewGroup;
 import android.widget.TextView;
 import android.widget.Toast;
-
+import com.android.tv.common.util.SystemPropertiesProxy;
 import com.android.tv.tuner.R;
 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.Track.AtscCaptionTrack;
+import com.android.tv.tuner.data.nano.Track.AtscCaptionTrack;
 import com.android.tv.tuner.util.GlobalSettingsUtils;
 import com.android.tv.tuner.util.StatusTextUtils;
 
 /** Executes {@link Session} overlay changes on the main thread. */
 /* package */ final class TunerSessionOverlay implements Handler.Callback {
-    private static final boolean DEBUG = false;
 
     /** Displays the given {@link String} message object in the message view. */
     public static final int MSG_UI_SHOW_MESSAGE = 1;
@@ -68,6 +67,8 @@
     /** Displays a toast signalling that a re-scan is required. Does not expect a message object. */
     public static final int MSG_UI_TOAST_RESCAN_NEEDED = 11;
 
+    private static final String USBTUNER_SHOW_DEBUG = "persist.tv.tuner.show_debug";
+
     private final Context mContext;
     private final Handler mHandler;
     private final View mOverlayView;
@@ -87,12 +88,13 @@
         mHandler = new Handler(this);
         LayoutInflater inflater =
                 (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        boolean showDebug = SystemPropertiesProxy.getBoolean(USBTUNER_SHOW_DEBUG, false);
         mOverlayView = inflater.inflate(R.layout.ut_overlay_view, null);
         mMessageLayout = mOverlayView.findViewById(R.id.message_layout);
         mMessageLayout.setVisibility(View.INVISIBLE);
         mMessageView = mOverlayView.findViewById(R.id.message);
         mStatusView = mOverlayView.findViewById(R.id.tuner_status);
-        mStatusView.setVisibility(DEBUG ? View.VISIBLE : View.INVISIBLE);
+        mStatusView.setVisibility(showDebug ? View.VISIBLE : View.INVISIBLE);
         mAudioStatusView = mOverlayView.findViewById(R.id.audio_status);
         mAudioStatusView.setVisibility(View.INVISIBLE);
         CaptionLayout captionLayout = mOverlayView.findViewById(R.id.caption);
diff --git a/tuner/src/com/android/tv/tuner/tvinput/TunerSessionWorker.java b/tuner/src/com/android/tv/tuner/tvinput/TunerSessionWorker.java
index 792dfaa..d3f9409 100644
--- a/tuner/src/com/android/tv/tuner/tvinput/TunerSessionWorker.java
+++ b/tuner/src/com/android/tv/tuner/tvinput/TunerSessionWorker.java
@@ -44,22 +44,22 @@
 import android.util.SparseArray;
 import android.view.Surface;
 import android.view.accessibility.CaptioningManager;
-
 import com.android.tv.common.CommonPreferences.TrickplaySetting;
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.common.TvContentRatingCache;
 import com.android.tv.common.compat.TvInputConstantCompat;
 import com.android.tv.common.customization.CustomizationManager;
 import com.android.tv.common.customization.CustomizationManager.TRICKPLAY_MODE;
-import com.android.tv.common.dev.DeveloperPreferences;
+import com.android.tv.common.experiments.Experiments;
 import com.android.tv.common.feature.CommonFeatures;
+import com.android.tv.common.util.SystemPropertiesProxy;
 import com.android.tv.tuner.data.Cea708Data;
-import com.android.tv.tuner.data.Channel;
 import com.android.tv.tuner.data.PsipData.EitItem;
 import com.android.tv.tuner.data.PsipData.TvTracksInterface;
-import com.android.tv.tuner.data.Track.AtscAudioTrack;
-import com.android.tv.tuner.data.Track.AtscCaptionTrack;
 import com.android.tv.tuner.data.TunerChannel;
+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.exoplayer.MpegTsPlayer;
 import com.android.tv.tuner.exoplayer.MpegTsRendererBuilder;
 import com.android.tv.tuner.exoplayer.buffer.BufferManager;
@@ -74,15 +74,10 @@
 import com.android.tv.tuner.tvinput.datamanager.ChannelDataManager;
 import com.android.tv.tuner.tvinput.debug.TunerDebug;
 import com.android.tv.tuner.util.StatusTextUtils;
-
 import com.google.android.exoplayer.ExoPlayer;
 import com.google.android.exoplayer.audio.AudioCapabilities;
-import com.google.auto.factory.AutoFactory;
-import com.google.auto.factory.Provided;
 import com.google.common.collect.ImmutableList;
-
-import com.android.tv.common.flags.LegacyFlags;
-
+import com.android.tv.common.flags.ConcurrentDvrPlaybackFlags;
 import java.io.File;
 import java.util.ArrayList;
 import java.util.Iterator;
@@ -108,6 +103,8 @@
     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
@@ -192,8 +189,6 @@
     private final int mMaxTrickplayBufferSizeMb;
     private final File mTrickplayBufferDir;
     private final @TRICKPLAY_MODE int mTrickplayModeCustomization;
-    private final LegacyFlags mLegacyFlags;
-    private final MpegTsRendererBuilder.Factory mMpegTsRendererBuilderFactory;
     private volatile Surface mSurface;
     private volatile float mVolume = 1.0f;
     private volatile boolean mCaptionEnabled;
@@ -236,44 +231,25 @@
     private boolean mIsActiveSession;
     private boolean mReleaseRequested; // Guarded by mReleaseLock
     private final Object mReleaseLock = new Object();
-    private Uri mChannelUri;
-    private Uri mRecordingUri;
-    private boolean mOnTuneUsesRecording = false;
+    private final ConcurrentDvrPlaybackFlags mConcurrentDvrPlaybackFlags;
 
     private int mSignalStrength;
     private long mRecordedProgramStartTimeMs;
 
-    /**
-     * Factory for {@link TunerSessionWorker}.
-     *
-     * <p>This wrapper class keeps other classes from needing to reference the {@link AutoFactory}
-     * generated class.
-     */
-    public interface Factory {
-        public TunerSessionWorker create(
-                Context context,
-                ChannelDataManager channelDataManager,
-                TunerSession tunerSession,
-                TunerSessionOverlay tunerSessionOverlay);
-    }
-
-    @AutoFactory(implementing = Factory.class)
     public TunerSessionWorker(
             Context context,
             ChannelDataManager channelDataManager,
             TunerSession tunerSession,
             TunerSessionOverlay tunerSessionOverlay,
-            @Provided LegacyFlags legacyFlags,
-            @Provided MpegTsRendererBuilder.Factory mpegTsRendererBuilderFactory,
-            @Provided TsDataSourceManager.Factory tsDataSourceManagerFactory) {
+            ConcurrentDvrPlaybackFlags concurrentDvrPlaybackFlags,
+            TsDataSourceManager.Factory tsDataSourceManagerFactory) {
         this(
                 context,
                 channelDataManager,
                 tunerSession,
                 tunerSessionOverlay,
                 null,
-                legacyFlags,
-                mpegTsRendererBuilderFactory,
+                concurrentDvrPlaybackFlags,
                 tsDataSourceManagerFactory);
     }
 
@@ -284,10 +260,9 @@
             TunerSession tunerSession,
             TunerSessionOverlay tunerSessionOverlay,
             @Nullable Handler handler,
-            LegacyFlags legacyFlags,
-            MpegTsRendererBuilder.Factory mpegTsRendererBuilderFactory,
+            ConcurrentDvrPlaybackFlags concurrentDvrPlaybackFlags,
             TsDataSourceManager.Factory tsDataSourceManagerFactory) {
-        mLegacyFlags = legacyFlags;
+        this.mConcurrentDvrPlaybackFlags = concurrentDvrPlaybackFlags;
         if (DEBUG) Log.d(TAG, "TunerSessionWorker created");
         mContext = context;
         if (handler != null) {
@@ -302,8 +277,6 @@
         mSession = tunerSession;
         mTunerSessionOverlay = tunerSessionOverlay;
         mChannelDataManager = channelDataManager;
-        mMpegTsRendererBuilderFactory = mpegTsRendererBuilderFactory;
-        mRecordingUri = null;
         mChannelDataManager.setListener(this);
         mChannelDataManager.checkDataVersion(mContext);
         mSourceManager = tsDataSourceManagerFactory.create(false);
@@ -320,7 +293,8 @@
                 (CaptioningManager) context.getSystemService(Context.CAPTIONING_SERVICE);
         mCaptionEnabled = captioningManager.isEnabled();
         mPlaybackParams.setSpeed(1.0f);
-        mMaxTrickplayBufferSizeMb = DeveloperPreferences.MAX_BUFFER_SIZE_MBYTES.get(context);
+        mMaxTrickplayBufferSizeMb =
+                SystemPropertiesProxy.getInt(MAX_BUFFER_SIZE_KEY, MAX_BUFFER_SIZE_DEF);
         mTrickplayModeCustomization = CustomizationManager.getTrickplayMode(context);
         if (mTrickplayModeCustomization
                 == CustomizationManager.TRICKPLAY_MODE_USE_EXTERNAL_STORAGE) {
@@ -513,11 +487,6 @@
             // Final status
             // notification of STATE_ENDED from MpegTsPlayer will be ignored afterwards.
             Log.i(TAG, "Player ended: end of stream");
-            if (mOnTuneUsesRecording) {
-                mRecordingUri = null;
-                mSession.notifyChannelRetuned(mChannelUri);
-                sendMessage(MSG_TUNE, mChannelUri);
-            }
             if (mChannel != null) {
                 sendMessage(MSG_RETRY_PLAYBACK, System.identityHashCode(mPlayer));
             }
@@ -546,10 +515,10 @@
     @Override
     public void onVideoSizeChanged(int width, int height, float pixelWidthHeight) {
         if (mChannel != null && mChannel.hasVideo()) {
-            updateVideoTrack(width, height, pixelWidthHeight);
+            updateVideoTrack(width, height);
         }
         if (mRecordingId != null) {
-            updateVideoTrack(width, height, pixelWidthHeight);
+            updateVideoTrack(width, height);
         }
     }
 
@@ -563,9 +532,6 @@
             } else {
                 mBufferStartTimeMs = mRecordStartTimeMs = System.currentTimeMillis();
             }
-            if (mOnTuneUsesRecording) {
-                mBufferStartTimeMs = mRecordStartTimeMs = mRecordedProgramStartTimeMs;
-            }
             notifyVideoAvailable();
             mReportedDrawnToSurface = true;
 
@@ -621,7 +587,7 @@
     // ChannelDataManager.ProgramInfoListener
     @Override
     public void onProgramsArrived(TunerChannel channel, List<EitItem> programs) {
-        sendMessage(MSG_SCHEDULE_OF_PROGRAMS, Pair.create(channel, programs));
+        sendMessage(MSG_SCHEDULE_OF_PROGRAMS, new Pair<>(channel, programs));
     }
 
     @Override
@@ -636,7 +602,7 @@
 
     @Override
     public void onRequestProgramsResponse(TunerChannel channel, List<EitItem> programs) {
-        sendMessage(MSG_PROGRAM_DATA_RESULT, Pair.create(channel, programs));
+        sendMessage(MSG_PROGRAM_DATA_RESULT, new Pair<>(channel, programs));
     }
 
     // PlaybackBufferListener
@@ -684,7 +650,7 @@
     }
 
     private static class RecordedProgram {
-        private final long mChannelId;
+        //        private final long mChannelId;
         private final String mDataUri;
         private final long mStartTimeMillis;
 
@@ -696,13 +662,14 @@
 
         public RecordedProgram(Cursor cursor) {
             int index = 0;
-            mChannelId = cursor.getLong(index++);
+            //            mChannelId = cursor.getLong(index++);
+            index++;
             mDataUri = cursor.getString(index++);
             mStartTimeMillis = cursor.getLong(index++);
         }
 
         public RecordedProgram(long channelId, String dataUri) {
-            mChannelId = channelId;
+            //            mChannelId = channelId;
             mDataUri = dataUri;
             mStartTimeMillis = 0;
         }
@@ -722,10 +689,6 @@
         public long getStartTime() {
             return mStartTimeMillis;
         }
-
-        public long getChannelId() {
-            return mChannelId;
-        }
     }
 
     private RecordedProgram getRecordedProgram(Uri recordedUri) {
@@ -748,13 +711,9 @@
         }
     }
 
-    private String parseRecording(Uri uri, long channelId) {
+    private String parseRecording(Uri uri) {
         RecordedProgram recording = getRecordedProgram(uri);
         if (recording != null) {
-            if (channelId != -1 && channelId != recording.getChannelId()) {
-                // Recorded URI is of some other channel
-                return null;
-            }
             mRecordedProgramStartTimeMs = recording.getStartTime();
             return recording.getDataUri();
         }
@@ -867,20 +826,10 @@
             mIsActiveSession = true;
         }
         String recording = null;
-        mOnTuneUsesRecording = false;
         long channelId = parseChannel(channelUri);
         TunerChannel channel = (channelId == -1) ? null : mChannelDataManager.getChannel(channelId);
-        mRecordingUri = mSession.getRecordingUri(channelUri);
         if (channelId == -1) {
-            recording = parseRecording(channelUri, channelId);
-
-        } else if (mRecordingUri != null) {
-            mChannelUri = channelUri;
-            recording = parseRecording(mRecordingUri, channelId);
-            if (recording != null) {
-                mOnTuneUsesRecording = true;
-                channel = null;
-            }
+            recording = parseRecording(channelUri);
         }
         if (channel == null && recording == null) {
             Log.w(TAG, "onTune() is failed. Can't find channel for " + channelUri);
@@ -1184,15 +1133,8 @@
         if (mPlayer == null) {
             return true;
         }
-        long seekPosMs = timeMs;
-        if (mRecordingId != null) {
-            long systemBufferTime = System.currentTimeMillis() - SEEK_MARGIN_MS;
-            if (seekPosMs > systemBufferTime) {
-                seekPosMs = systemBufferTime;
-            }
-        }
         setTrickplayEnabledIfNeeded();
-        doTimeShiftSeekTo(seekPosMs);
+        doTimeShiftSeekTo(timeMs);
         return true;
     }
 
@@ -1490,7 +1432,8 @@
         }
         MpegTsPlayer player =
                 new MpegTsPlayer(
-                        mMpegTsRendererBuilderFactory.create(mContext, bufferManager, this),
+                        new MpegTsRendererBuilder(
+                                mContext, bufferManager, this, mConcurrentDvrPlaybackFlags),
                         mHandler,
                         mSourceManager,
                         capabilities,
@@ -1501,7 +1444,7 @@
         player.setVideoEventListener(this);
         player.setCaptionServiceNumber(
                 mCaptionTrack != null
-                        ? mCaptionTrack.getServiceNumber()
+                        ? mCaptionTrack.serviceNumber
                         : Cea708Data.EMPTY_SERVICE_NUMBER);
         return player;
     }
@@ -1511,7 +1454,7 @@
             mTunerSessionOverlay.sendUiMessage(
                     TunerSessionOverlay.MSG_UI_START_CAPTION_TRACK, mCaptionTrack);
             if (mPlayer != null) {
-                mPlayer.setCaptionServiceNumber(mCaptionTrack.getServiceNumber());
+                mPlayer.setCaptionServiceNumber(mCaptionTrack.serviceNumber);
             }
         }
     }
@@ -1568,13 +1511,12 @@
         }
     }
 
-    private void updateVideoTrack(int width, int height, float pixelWidthHeight) {
+    private void updateVideoTrack(int width, int height) {
         removeTvTracks(TvTrackInfo.TYPE_VIDEO);
         mTvTracks.add(
                 new TvTrackInfo.Builder(TvTrackInfo.TYPE_VIDEO, VIDEO_TRACK_ID)
                         .setVideoWidth(width)
                         .setVideoHeight(height)
-                        .setVideoPixelAspectRatio(pixelWidthHeight)
                         .build());
         mSession.notifyTracksChanged(mTvTracks);
         mSession.notifyTrackSelected(TvTrackInfo.TYPE_VIDEO, VIDEO_TRACK_ID);
@@ -1588,7 +1530,7 @@
         if (audioTracks != null) {
             int index = 0;
             for (AtscAudioTrack audioTrack : audioTracks) {
-                audioTrack = audioTrack.toBuilder().setIndex(index).build();
+                audioTrack.index = index;
                 mAudioTrackMap.put(index, audioTrack);
                 ++index;
             }
@@ -1618,10 +1560,10 @@
             String language =
                     !TextUtils.isEmpty(infoFromPlayer.language)
                             ? infoFromPlayer.language
-                            : (infoFromEit != null && infoFromEit.hasLanguage())
-                                    ? infoFromEit.getLanguage()
-                                    : (infoFromVct != null && infoFromVct.hasLanguage())
-                                            ? infoFromVct.getLanguage()
+                            : (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);
@@ -1642,20 +1584,20 @@
         mCaptionTrackMap.clear();
         if (captionTracks != null) {
             for (AtscCaptionTrack captionTrack : captionTracks) {
-                if (mCaptionTrackMap.indexOfKey(captionTrack.getServiceNumber()) >= 0) {
+                if (mCaptionTrackMap.indexOfKey(captionTrack.serviceNumber) >= 0) {
                     continue;
                 }
-                String language = captionTrack.getLanguage();
+                String language = captionTrack.language;
 
                 // The service number of the caption service is used for track id of a subtitle.
                 // Later, when a subtitle is chosen, track id will be passed on to TsParser.
                 TvTrackInfo.Builder builder =
                         new TvTrackInfo.Builder(
                                 TvTrackInfo.TYPE_SUBTITLE,
-                                SUBTITLE_TRACK_PREFIX + captionTrack.getServiceNumber());
+                                SUBTITLE_TRACK_PREFIX + captionTrack.serviceNumber);
                 builder.setLanguage(language);
                 mTvTracks.add(builder.build());
-                mCaptionTrackMap.put(captionTrack.getServiceNumber(), captionTrack);
+                mCaptionTrackMap.put(captionTrack.serviceNumber, captionTrack);
             }
         }
         mSession.notifyTracksChanged(mTvTracks);
@@ -1835,9 +1777,6 @@
         } else {
             mBufferStartTimeMs = mRecordStartTimeMs = System.currentTimeMillis();
         }
-        if (mOnTuneUsesRecording) {
-            mBufferStartTimeMs = mRecordStartTimeMs = mRecordedProgramStartTimeMs;
-        }
         mLastPositionMs = 0;
         mCaptionTrack = null;
         mSignalStrength = TvInputConstantCompat.SIGNAL_STRENGTH_UNKNOWN;
@@ -1845,14 +1784,6 @@
             mSession.notifySignalStrength(mSignalStrength);
         }
         mHandler.sendEmptyMessage(MSG_PARENTAL_CONTROLS);
-        if (mOnTuneUsesRecording) {
-            mHandler.obtainMessage(
-                            MSG_TIMESHIFT_SEEK_TO,
-                            1,
-                            0,
-                            System.currentTimeMillis() - SEEK_MARGIN_MS)
-                    .sendToTarget();
-        }
     }
 
     private void doReschedulePrograms() {
@@ -1874,7 +1805,7 @@
                                 + " current program: "
                                 + getCurrentProgram());
             }
-            mHandler.obtainMessage(MSG_SCHEDULE_OF_PROGRAMS, Pair.create(mChannel, mPrograms))
+            mHandler.obtainMessage(MSG_SCHEDULE_OF_PROGRAMS, new Pair<>(mChannel, mPrograms))
                     .sendToTarget();
         }
         mHandler.removeMessages(MSG_RESCHEDULE_PROGRAMS);
@@ -2035,12 +1966,10 @@
     private void doDiscoverCaptionServiceNumber(int serviceNumber) {
         int index = mCaptionTrackMap.indexOfKey(serviceNumber);
         if (index < 0) {
-            AtscCaptionTrack captionTrack =
-                    AtscCaptionTrack.newBuilder()
-                            .setServiceNumber(serviceNumber)
-                            .setWideAspectRatio(false)
-                            .setEasyReader(false)
-                            .build();
+            AtscCaptionTrack captionTrack = new AtscCaptionTrack();
+            captionTrack.serviceNumber = serviceNumber;
+            captionTrack.wideAspectRatio = false;
+            captionTrack.easyReader = false;
             mCaptionTrackMap.put(serviceNumber, captionTrack);
             mTvTracks.add(
                     new TvTrackInfo.Builder(
@@ -2059,7 +1988,7 @@
         ImmutableList<TvContentRating> ratings =
                 mTvContentRatingCache.getRatings(currentProgram.getContentRating());
         if ((ratings == null || ratings.isEmpty())) {
-            if (mLegacyFlags.enableUnratedContentSettings()) {
+            if (Experiments.ENABLE_UNRATED_CONTENT_SETTINGS.get()) {
                 ratings = ImmutableList.of(TvContentRating.UNRATED);
             } else {
                 ratings = NO_CONTENT_RATINGS;
diff --git a/tuner/src/com/android/tv/tuner/tvinput/TunerSessionWorkerExoV2.java b/tuner/src/com/android/tv/tuner/tvinput/TunerSessionWorkerExoV2.java
index f56e487..82afff1 100644
--- a/tuner/src/com/android/tv/tuner/tvinput/TunerSessionWorkerExoV2.java
+++ b/tuner/src/com/android/tv/tuner/tvinput/TunerSessionWorkerExoV2.java
@@ -44,22 +44,22 @@
 import android.util.SparseArray;
 import android.view.Surface;
 import android.view.accessibility.CaptioningManager;
-
 import com.android.tv.common.CommonPreferences.TrickplaySetting;
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.common.TvContentRatingCache;
 import com.android.tv.common.compat.TvInputConstantCompat;
 import com.android.tv.common.customization.CustomizationManager;
 import com.android.tv.common.customization.CustomizationManager.TRICKPLAY_MODE;
-import com.android.tv.common.dev.DeveloperPreferences;
+import com.android.tv.common.experiments.Experiments;
 import com.android.tv.common.feature.CommonFeatures;
+import com.android.tv.common.util.SystemPropertiesProxy;
 import com.android.tv.tuner.data.Cea708Data;
-import com.android.tv.tuner.data.Channel;
 import com.android.tv.tuner.data.PsipData.EitItem;
 import com.android.tv.tuner.data.PsipData.TvTracksInterface;
-import com.android.tv.tuner.data.Track.AtscAudioTrack;
-import com.android.tv.tuner.data.Track.AtscCaptionTrack;
 import com.android.tv.tuner.data.TunerChannel;
+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.exoplayer.MpegTsPlayer;
 import com.android.tv.tuner.exoplayer.MpegTsRendererBuilder;
 import com.android.tv.tuner.exoplayer.buffer.BufferManager;
@@ -74,15 +74,10 @@
 import com.android.tv.tuner.tvinput.datamanager.ChannelDataManager;
 import com.android.tv.tuner.tvinput.debug.TunerDebug;
 import com.android.tv.tuner.util.StatusTextUtils;
-
 import com.google.android.exoplayer.ExoPlayer;
 import com.google.android.exoplayer.audio.AudioCapabilities;
-import com.google.auto.factory.AutoFactory;
-import com.google.auto.factory.Provided;
 import com.google.common.collect.ImmutableList;
-
-import com.android.tv.common.flags.LegacyFlags;
-
+import com.android.tv.common.flags.ConcurrentDvrPlaybackFlags;
 import java.io.File;
 import java.util.ArrayList;
 import java.util.Iterator;
@@ -105,6 +100,8 @@
     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
@@ -191,7 +188,6 @@
     private final int mMaxTrickplayBufferSizeMb;
     private final File mTrickplayBufferDir;
     private final @TRICKPLAY_MODE int mTrickplayModeCustomization;
-    private final MpegTsRendererBuilder.Factory mMpegTsRendererBuilderFactory;
     private volatile Surface mSurface;
     private volatile float mVolume = 1.0f;
     private volatile boolean mCaptionEnabled;
@@ -234,45 +230,25 @@
     private boolean mIsActiveSession;
     private boolean mReleaseRequested; // Guarded by mReleaseLock
     private final Object mReleaseLock = new Object();
-    private final LegacyFlags mLegacyFlags;
-    private Uri mChannelUri;
-    private Uri mRecordingUri;
-    private boolean mOnTuneUsesRecording = false;
+    private final ConcurrentDvrPlaybackFlags mConcurrentDvrPlaybackFlags;
 
     private int mSignalStrength;
     private long mRecordedProgramStartTimeMs;
 
-    /**
-     * Factory for {@link TunerSessionWorkerExoV2}.
-     *
-     * <p>This wrapper class keeps other classes from needing to reference the {@link AutoFactory}
-     * generated class.
-     */
-    public interface Factory {
-        public TunerSessionWorkerExoV2 create(
-                Context context,
-                ChannelDataManager channelDataManager,
-                TunerSessionExoV2 tunerSession,
-                TunerSessionOverlay tunerSessionOverlay);
-    }
-
-    @AutoFactory(implementing = Factory.class)
     public TunerSessionWorkerExoV2(
             Context context,
             ChannelDataManager channelDataManager,
             TunerSessionExoV2 tunerSession,
             TunerSessionOverlay tunerSessionOverlay,
-            @Provided LegacyFlags legacyFlags,
-            @Provided MpegTsRendererBuilder.Factory mpegTsRendererBuilderFactory,
-            @Provided TsDataSourceManager.Factory tsDataSourceManagerFactory) {
+            ConcurrentDvrPlaybackFlags concurrentDvrPlaybackFlags,
+            TsDataSourceManager.Factory tsDataSourceManagerFactory) {
         this(
                 context,
                 channelDataManager,
                 tunerSession,
                 tunerSessionOverlay,
                 null,
-                legacyFlags,
-                mpegTsRendererBuilderFactory,
+                concurrentDvrPlaybackFlags,
                 tsDataSourceManagerFactory);
     }
 
@@ -283,10 +259,9 @@
             TunerSessionExoV2 tunerSession,
             TunerSessionOverlay tunerSessionOverlay,
             @Nullable Handler handler,
-            LegacyFlags legacyFlags,
-            MpegTsRendererBuilder.Factory mpegTsRendererBuilderFactory,
+            ConcurrentDvrPlaybackFlags concurrentDvrPlaybackFlags,
             TsDataSourceManager.Factory tsDataSourceManagerFactory) {
-        mLegacyFlags = legacyFlags;
+        mConcurrentDvrPlaybackFlags = concurrentDvrPlaybackFlags;
         if (DEBUG) {
             Log.d(TAG, "TunerSessionWorkerExoV2 created");
         }
@@ -303,8 +278,6 @@
         mSession = tunerSession;
         mTunerSessionOverlay = tunerSessionOverlay;
         mChannelDataManager = channelDataManager;
-        mMpegTsRendererBuilderFactory = mpegTsRendererBuilderFactory;
-        mRecordingUri = null;
         mChannelDataManager.setListener(this);
         mChannelDataManager.checkDataVersion(mContext);
         mSourceManager = tsDataSourceManagerFactory.create(false);
@@ -321,7 +294,8 @@
                 (CaptioningManager) context.getSystemService(Context.CAPTIONING_SERVICE);
         mCaptionEnabled = captioningManager.isEnabled();
         mPlaybackParams.setSpeed(1.0f);
-        mMaxTrickplayBufferSizeMb = DeveloperPreferences.MAX_BUFFER_SIZE_MBYTES.get(context);
+        mMaxTrickplayBufferSizeMb =
+                SystemPropertiesProxy.getInt(MAX_BUFFER_SIZE_KEY, MAX_BUFFER_SIZE_DEF);
         mTrickplayModeCustomization = CustomizationManager.getTrickplayMode(context);
         if (mTrickplayModeCustomization
                 == CustomizationManager.TRICKPLAY_MODE_USE_EXTERNAL_STORAGE) {
@@ -519,11 +493,6 @@
             // Final status
             // notification of STATE_ENDED from MpegTsPlayer will be ignored afterwards.
             Log.i(TAG, "Player ended: end of stream");
-            if (mOnTuneUsesRecording) {
-                mRecordingUri = null;
-                mSession.notifyChannelRetuned(mChannelUri);
-                sendMessage(MSG_TUNE, mChannelUri);
-            }
             if (mChannel != null) {
                 sendMessage(MSG_RETRY_PLAYBACK, System.identityHashCode(mPlayer));
             }
@@ -552,10 +521,10 @@
     @Override
     public void onVideoSizeChanged(int width, int height, float pixelWidthHeight) {
         if (mChannel != null && mChannel.hasVideo()) {
-            updateVideoTrack(width, height, pixelWidthHeight);
+            updateVideoTrack(width, height);
         }
         if (mRecordingId != null) {
-            updateVideoTrack(width, height, pixelWidthHeight);
+            updateVideoTrack(width, height);
         }
     }
 
@@ -571,9 +540,6 @@
             } else {
                 mBufferStartTimeMs = mRecordStartTimeMs = System.currentTimeMillis();
             }
-            if (mOnTuneUsesRecording) {
-                mBufferStartTimeMs = mRecordStartTimeMs = mRecordedProgramStartTimeMs;
-            }
             notifyVideoAvailable();
             mReportedDrawnToSurface = true;
 
@@ -629,7 +595,7 @@
     // ChannelDataManager.ProgramInfoListener
     @Override
     public void onProgramsArrived(TunerChannel channel, List<EitItem> programs) {
-        sendMessage(MSG_SCHEDULE_OF_PROGRAMS, Pair.create(channel, programs));
+        sendMessage(MSG_SCHEDULE_OF_PROGRAMS, new Pair<>(channel, programs));
     }
 
     @Override
@@ -644,7 +610,7 @@
 
     @Override
     public void onRequestProgramsResponse(TunerChannel channel, List<EitItem> programs) {
-        sendMessage(MSG_PROGRAM_DATA_RESULT, Pair.create(channel, programs));
+        sendMessage(MSG_PROGRAM_DATA_RESULT, new Pair<>(channel, programs));
     }
 
     // PlaybackBufferListener
@@ -692,7 +658,7 @@
     }
 
     private static class RecordedProgram {
-        private final long mChannelId;
+        //        private final long mChannelId;
         private final String mDataUri;
         private final long mStartTimeMillis;
 
@@ -704,13 +670,14 @@
 
         public RecordedProgram(Cursor cursor) {
             int index = 0;
-            mChannelId = cursor.getLong(index++);
+            //            mChannelId = cursor.getLong(index++);
+            index++;
             mDataUri = cursor.getString(index++);
             mStartTimeMillis = cursor.getLong(index++);
         }
 
         public RecordedProgram(long channelId, String dataUri) {
-            mChannelId = channelId;
+            //            mChannelId = channelId;
             mDataUri = dataUri;
             mStartTimeMillis = 0;
         }
@@ -730,10 +697,6 @@
         public long getStartTime() {
             return mStartTimeMillis;
         }
-
-        public long getChannelId() {
-            return mChannelId;
-        }
     }
 
     private RecordedProgram getRecordedProgram(Uri recordedUri) {
@@ -758,13 +721,9 @@
         }
     }
 
-    private String parseRecording(Uri uri, long channelId) {
+    private String parseRecording(Uri uri) {
         RecordedProgram recording = getRecordedProgram(uri);
         if (recording != null) {
-            if (channelId != -1 && channelId != recording.getChannelId()) {
-                // Recorded URI is of some other channel
-                return null;
-            }
             mRecordedProgramStartTimeMs = recording.getStartTime();
             return recording.getDataUri();
         }
@@ -877,19 +836,10 @@
             mIsActiveSession = true;
         }
         String recording = null;
-        mOnTuneUsesRecording = false;
         long channelId = parseChannel(channelUri);
         TunerChannel channel = (channelId == -1) ? null : mChannelDataManager.getChannel(channelId);
-        mRecordingUri = mSession.getRecordingUri(channelUri);
         if (channelId == -1) {
-            recording = parseRecording(channelUri, channelId);
-        } else if (mRecordingUri != null) {
-            mChannelUri = channelUri;
-            recording = parseRecording(mRecordingUri, channelId);
-            if (recording != null) {
-                mOnTuneUsesRecording = true;
-                channel = null;
-            }
+            recording = parseRecording(channelUri);
         }
         if (channel == null && recording == null) {
             Log.w(TAG, "onTune() is failed. Can't find channel for " + channelUri);
@@ -1492,7 +1442,8 @@
         }
         MpegTsPlayer player =
                 new MpegTsPlayer(
-                        mMpegTsRendererBuilderFactory.create(mContext, bufferManager, this),
+                        new MpegTsRendererBuilder(
+                                mContext, bufferManager, this, mConcurrentDvrPlaybackFlags),
                         mHandler,
                         mSourceManager,
                         capabilities,
@@ -1505,7 +1456,7 @@
         player.setVideoEventListener(this);
         player.setCaptionServiceNumber(
                 mCaptionTrack != null
-                        ? mCaptionTrack.getServiceNumber()
+                        ? mCaptionTrack.serviceNumber
                         : Cea708Data.EMPTY_SERVICE_NUMBER);
         return player;
     }
@@ -1515,7 +1466,7 @@
             mTunerSessionOverlay.sendUiMessage(
                     TunerSessionOverlay.MSG_UI_START_CAPTION_TRACK, mCaptionTrack);
             if (mPlayer != null) {
-                mPlayer.setCaptionServiceNumber(mCaptionTrack.getServiceNumber());
+                mPlayer.setCaptionServiceNumber(mCaptionTrack.serviceNumber);
             }
         }
     }
@@ -1572,13 +1523,12 @@
         }
     }
 
-    private void updateVideoTrack(int width, int height, float pixelWidthHeight) {
+    private void updateVideoTrack(int width, int height) {
         removeTvTracks(TvTrackInfo.TYPE_VIDEO);
         mTvTracks.add(
                 new TvTrackInfo.Builder(TvTrackInfo.TYPE_VIDEO, VIDEO_TRACK_ID)
                         .setVideoWidth(width)
                         .setVideoHeight(height)
-                        .setVideoPixelAspectRatio(pixelWidthHeight)
                         .build());
         mSession.notifyTracksChanged(mTvTracks);
         mSession.notifyTrackSelected(TvTrackInfo.TYPE_VIDEO, VIDEO_TRACK_ID);
@@ -1592,7 +1542,7 @@
         if (audioTracks != null) {
             int index = 0;
             for (AtscAudioTrack audioTrack : audioTracks) {
-                audioTrack = audioTrack.toBuilder().setIndex(index).build();
+                audioTrack.index = index;
                 mAudioTrackMap.put(index, audioTrack);
                 ++index;
             }
@@ -1622,10 +1572,10 @@
             String language =
                     !TextUtils.isEmpty(infoFromPlayer.language)
                             ? infoFromPlayer.language
-                            : (infoFromEit != null && infoFromEit.hasLanguage())
-                                    ? infoFromEit.getLanguage()
-                                    : (infoFromVct != null && infoFromVct.hasLanguage())
-                                            ? infoFromVct.getLanguage()
+                            : (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);
@@ -1646,20 +1596,20 @@
         mCaptionTrackMap.clear();
         if (captionTracks != null) {
             for (AtscCaptionTrack captionTrack : captionTracks) {
-                if (mCaptionTrackMap.indexOfKey(captionTrack.getServiceNumber()) >= 0) {
+                if (mCaptionTrackMap.indexOfKey(captionTrack.serviceNumber) >= 0) {
                     continue;
                 }
-                String language = captionTrack.getLanguage();
+                String language = captionTrack.language;
 
                 // The service number of the caption service is used for track id of a subtitle.
                 // Later, when a subtitle is chosen, track id will be passed on to TsParser.
                 TvTrackInfo.Builder builder =
                         new TvTrackInfo.Builder(
                                 TvTrackInfo.TYPE_SUBTITLE,
-                                SUBTITLE_TRACK_PREFIX + captionTrack.getServiceNumber());
+                                SUBTITLE_TRACK_PREFIX + captionTrack.serviceNumber);
                 builder.setLanguage(language);
                 mTvTracks.add(builder.build());
-                mCaptionTrackMap.put(captionTrack.getServiceNumber(), captionTrack);
+                mCaptionTrackMap.put(captionTrack.serviceNumber, captionTrack);
             }
         }
         mSession.notifyTracksChanged(mTvTracks);
@@ -1841,9 +1791,6 @@
         } else {
             mBufferStartTimeMs = mRecordStartTimeMs = System.currentTimeMillis();
         }
-        if (mOnTuneUsesRecording) {
-            mBufferStartTimeMs = mRecordStartTimeMs = mRecordedProgramStartTimeMs;
-        }
         mLastPositionMs = 0;
         mCaptionTrack = null;
         mSignalStrength = TvInputConstantCompat.SIGNAL_STRENGTH_UNKNOWN;
@@ -1851,14 +1798,6 @@
             mSession.notifySignalStrength(mSignalStrength);
         }
         mHandler.sendEmptyMessage(MSG_PARENTAL_CONTROLS);
-        if (mOnTuneUsesRecording) {
-            mHandler.obtainMessage(
-                            MSG_TIMESHIFT_SEEK_TO,
-                            1,
-                            0,
-                            System.currentTimeMillis() - SEEK_MARGIN_MS)
-                    .sendToTarget();
-        }
     }
 
     private void doReschedulePrograms() {
@@ -1880,7 +1819,7 @@
                                 + " current program: "
                                 + getCurrentProgram());
             }
-            mHandler.obtainMessage(MSG_SCHEDULE_OF_PROGRAMS, Pair.create(mChannel, mPrograms))
+            mHandler.obtainMessage(MSG_SCHEDULE_OF_PROGRAMS, new Pair<>(mChannel, mPrograms))
                     .sendToTarget();
         }
         mHandler.removeMessages(MSG_RESCHEDULE_PROGRAMS);
@@ -2041,13 +1980,10 @@
     private void doDiscoverCaptionServiceNumber(int serviceNumber) {
         int index = mCaptionTrackMap.indexOfKey(serviceNumber);
         if (index < 0) {
-            AtscCaptionTrack.Builder captionTrackBuilder = AtscCaptionTrack.newBuilder();
-            AtscCaptionTrack captionTrack =
-                    captionTrackBuilder
-                            .setServiceNumber(serviceNumber)
-                            .setWideAspectRatio(false)
-                            .setEasyReader(false)
-                            .build();
+            AtscCaptionTrack captionTrack = new AtscCaptionTrack();
+            captionTrack.serviceNumber = serviceNumber;
+            captionTrack.wideAspectRatio = false;
+            captionTrack.easyReader = false;
             mCaptionTrackMap.put(serviceNumber, captionTrack);
             mTvTracks.add(
                     new TvTrackInfo.Builder(
@@ -2066,7 +2002,7 @@
         ImmutableList<TvContentRating> ratings =
                 mTvContentRatingCache.getRatings(currentProgram.getContentRating());
         if ((ratings == null || ratings.isEmpty())) {
-            if (mLegacyFlags.enableUnratedContentSettings()) {
+            if (Experiments.ENABLE_UNRATED_CONTENT_SETTINGS.get()) {
                 ratings = ImmutableList.of(TvContentRating.UNRATED);
             } else {
                 ratings = NO_CONTENT_RATINGS;
diff --git a/tuner/src/com/android/tv/tuner/tvinput/datamanager/ChannelDataManager.java b/tuner/src/com/android/tv/tuner/tvinput/datamanager/ChannelDataManager.java
index 447618a..585b28b 100644
--- a/tuner/src/com/android/tv/tuner/tvinput/datamanager/ChannelDataManager.java
+++ b/tuner/src/com/android/tv/tuner/tvinput/datamanager/ChannelDataManager.java
@@ -29,10 +29,11 @@
 import android.os.HandlerThread;
 import android.os.Message;
 import android.os.RemoteException;
-import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.text.format.DateUtils;
 import android.util.Log;
+import com.android.tv.common.singletons.HasSingletons;
+import com.android.tv.common.singletons.HasTvInputId;
 import com.android.tv.common.util.PermissionUtils;
 import com.android.tv.tuner.data.PsipData.EitItem;
 import com.android.tv.tuner.data.TunerChannel;
@@ -50,7 +51,7 @@
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 
-/** Manages the channel info and EPG data for a specific inputId. */
+/** Manages the channel info and EPG data through {@link TvInputManager}. */
 public class ChannelDataManager implements Handler.Callback {
     private static final String TAG = "ChannelDataManager";
 
@@ -145,9 +146,9 @@
         void onChannelHandlingDone();
     }
 
-    public ChannelDataManager(Context context, String inputId) {
+    public ChannelDataManager(Context context) {
         mContext = context;
-        mInputId = inputId;
+        mInputId = HasSingletons.get(HasTvInputId.class, context).getEmbeddedTunerInputId();
         mChannelsUri = TvContract.buildChannelsUriForInput(mInputId);
         mTunerChannelMap = new ConcurrentHashMap<>();
         mTunerChannelIdMap = new ConcurrentSkipListMap<>();
@@ -381,12 +382,6 @@
         return false;
     }
 
-    @NonNull
-    @Override
-    public String toString() {
-        return "ChannelDataManager[" + mInputId + "]";
-    }
-
     // Private methods
     private void handleEvents(TunerChannel channel, List<EitItem> items) {
         long channelId = getChannelId(channel);
diff --git a/tuner/src/com/android/tv/tuner/tvinput/factory/TunerRecordingSessionFactory.java b/tuner/src/com/android/tv/tuner/tvinput/factory/TunerRecordingSessionFactory.java
deleted file mode 100644
index c595075..0000000
--- a/tuner/src/com/android/tv/tuner/tvinput/factory/TunerRecordingSessionFactory.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2019 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.tvinput.factory;
-
-import android.media.tv.TvInputService.RecordingSession;
-
-import com.android.tv.tuner.tvinput.datamanager.ChannelDataManager;
-
-/** {@link RecordingSession} factory */
-public interface TunerRecordingSessionFactory {
-
-    /** Called when a recording session is released */
-    interface RecordingSessionReleasedCallback {
-
-        /**
-         * Called when the given recording session is released.
-         *
-         * @param session The recording session that has been released.
-         */
-        void onReleased(RecordingSession session);
-    }
-
-    RecordingSession create(
-            String inputId,
-            RecordingSessionReleasedCallback releasedCallback,
-            ChannelDataManager channelDataManager);
-}
diff --git a/tuner/src/com/android/tv/tuner/tvinput/factory/TunerSessionFactory.java b/tuner/src/com/android/tv/tuner/tvinput/factory/TunerSessionFactory.java
index e22562a..a27cb22 100644
--- a/tuner/src/com/android/tv/tuner/tvinput/factory/TunerSessionFactory.java
+++ b/tuner/src/com/android/tv/tuner/tvinput/factory/TunerSessionFactory.java
@@ -1,24 +1,7 @@
-/*
- * Copyright (C) 2019 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.tvinput.factory;
 
+import android.content.Context;
 import android.media.tv.TvInputService.Session;
-import android.net.Uri;
-
 import com.android.tv.tuner.tvinput.datamanager.ChannelDataManager;
 
 /** {@link android.media.tv.TvInputService.Session} factory */
@@ -35,19 +18,8 @@
         void onReleased(Session session);
     }
 
-    /** Called when recording URI is required for playback */
-    interface SessionRecordingCallback {
-
-        /**
-         * Called when recording URI is required for playback.
-         *
-         * @param channelUri for which recording URI is requested.
-         */
-        Uri getRecordingUri(Uri channelUri);
-    }
-
     Session create(
+            Context context,
             ChannelDataManager channelDataManager,
-            SessionReleasedCallback releasedCallback,
-            SessionRecordingCallback recordingCallback);
+            SessionReleasedCallback releasedCallback);
 }
diff --git a/tuner/src/com/android/tv/tuner/tvinput/factory/TunerSessionFactoryImpl.java b/tuner/src/com/android/tv/tuner/tvinput/factory/TunerSessionFactoryImpl.java
new file mode 100644
index 0000000..54e959e
--- /dev/null
+++ b/tuner/src/com/android/tv/tuner/tvinput/factory/TunerSessionFactoryImpl.java
@@ -0,0 +1,49 @@
+package com.android.tv.tuner.tvinput.factory;
+
+import android.content.Context;
+import android.media.tv.TvInputService.Session;
+import com.android.tv.tuner.source.TsDataSourceManager;
+import com.android.tv.tuner.tvinput.TunerSession;
+import com.android.tv.tuner.tvinput.TunerSessionExoV2;
+import com.android.tv.tuner.tvinput.datamanager.ChannelDataManager;
+import com.android.tv.common.flags.ConcurrentDvrPlaybackFlags;
+import com.android.tv.common.flags.TunerFlags;
+import javax.inject.Inject;
+
+/** Creates a {@link TunerSessionFactory}. */
+public class TunerSessionFactoryImpl implements TunerSessionFactory {
+
+    private final TunerFlags mTunerFlags;
+    private final ConcurrentDvrPlaybackFlags mConcurrentDvrPlaybackFlags;
+    private final TsDataSourceManager.Factory mTsDataSourceManagerFactory;
+
+    @Inject
+    public TunerSessionFactoryImpl(
+            TunerFlags tunerFlags,
+            ConcurrentDvrPlaybackFlags concurrentDvrPlaybackFlags,
+            TsDataSourceManager.Factory tsDataSourceManagerFactory) {
+        mTunerFlags = tunerFlags;
+        mConcurrentDvrPlaybackFlags = concurrentDvrPlaybackFlags;
+        mTsDataSourceManagerFactory = tsDataSourceManagerFactory;
+    }
+
+    @Override
+    public Session create(
+            Context context,
+            ChannelDataManager channelDataManager,
+            SessionReleasedCallback releasedCallback) {
+        return mTunerFlags.useExoplayerV2()
+                ? new TunerSessionExoV2(
+                        context,
+                        channelDataManager,
+                        releasedCallback,
+                        mConcurrentDvrPlaybackFlags,
+                        mTsDataSourceManagerFactory)
+                : new TunerSession(
+                        context,
+                        channelDataManager,
+                        releasedCallback,
+                        mConcurrentDvrPlaybackFlags,
+                        mTsDataSourceManagerFactory);
+    }
+}
diff --git a/tuner/tests/robotests/Android.mk b/tuner/tests/robotests/Android.mk
deleted file mode 100644
index 16af9e9..0000000
--- a/tuner/tests/robotests/Android.mk
+++ /dev/null
@@ -1,68 +0,0 @@
-#############################################################
-# Tv Robolectric test target.                               #
-#############################################################
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := TvTunerRoboTests
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-
-LOCAL_SRC_FILES := $(call all-java-files-under, javatests)
-
-LOCAL_JAVA_LIBRARIES := \
-    Robolectric_all-target \
-    mockito-robolectric-prebuilt \
-    robolectric_android-all-stub \
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    tv-lib-dagger
-
-LOCAL_STATIC_ANDROID_LIBRARIES := \
-    androidx.test.core \
-    tv-lib-dagger-android \
-    tv-test-common \
-    tv-test-common-robo \
-    tv-tuner-testing \
-
-LOCAL_ANNOTATION_PROCESSORS := \
-    tv-lib-dagger-android-processor \
-    tv-lib-dagger-compiler \
-
-LOCAL_ANNOTATION_PROCESSOR_CLASSES := \
-  dagger.internal.codegen.ComponentProcessor,dagger.android.processor.AndroidProcessor
-
-LOCAL_INSTRUMENTATION_FOR := LiveTv
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-#############################################################
-# Tv runner target to run the previous target.              #
-#############################################################
-include $(CLEAR_VARS)
-LOCAL_MODULE := RunTvTunerRoboTests
-
-BASE_DIR = com/android/tv/tuner
-EXCLUDE_FILES := \
-    $(BASE_DIR)/dvb/DvbTunerHalTest.java \
-    $(BASE_DIR)/exoplayer/tests/SampleSourceExtractorTest.java \
-
-LOCAL_ROBOTEST_FILES := $(call find-files-in-subdirs,$(LOCAL_PATH)/javatests,*Test.java,.)
-LOCAL_ROBOTEST_FILES := $(filter-out $(EXCLUDE_FILES),$(LOCAL_ROBOTEST_FILES))
-
-LOCAL_JAVA_LIBRARIES := \
-    Robolectric_all-target \
-    TvTunerRoboTests \
-    mockito-robolectric-prebuilt \
-    robolectric_android-all-stub \
-    tv-lib-truth \
-    tv-test-common \
-    tv-test-common-robo \
-    tv-tuner-testing \
-
-LOCAL_TEST_PACKAGE := LiveTv
-
-LOCAL_ROBOTEST_TIMEOUT := 36000
-
-include external/robolectric-shadows/run_robotests.mk
diff --git a/tuner/tests/robotests/javatests/com/android/tv/tuner/data/SectionParserTest.java b/tuner/tests/robotests/javatests/com/android/tv/tuner/data/SectionParserTest.java
deleted file mode 100644
index e40abdc..0000000
--- a/tuner/tests/robotests/javatests/com/android/tv/tuner/data/SectionParserTest.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * 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.data;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
-
-import com.android.tv.testing.constants.ConfigConstants;
-import com.android.tv.tuner.data.PsipData.ContentAdvisoryDescriptor;
-import com.android.tv.tuner.data.PsipData.RatingRegion;
-import com.android.tv.tuner.data.PsipData.RegionalRating;
-import com.android.tv.tuner.data.PsipData.TsDescriptor;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/** Tests for {@link com.android.tv.tuner.data.SectionParser}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-public class SectionParserTest {
-    private static final Map<String, String> US_RATING_MAP = new HashMap<>();
-    private static final int RATING_REGION_US = 1;
-
-    static {
-        // These mappings are from table 3 of ANSI-CEA-766-D
-        US_RATING_MAP.put("1 0 0 0 0 0 0 X", ""); // TV-None
-        US_RATING_MAP.put("0 0 0 0 0 1 0 X", "com.android.tv/US_TV/US_TV_Y");
-        US_RATING_MAP.put("0 0 0 0 0 2 0 X", "com.android.tv/US_TV/US_TV_Y7");
-        US_RATING_MAP.put("0 0 0 0 0 2 1 X", "com.android.tv/US_TV/US_TV_Y7/US_TV_FV");
-        US_RATING_MAP.put("2 0 0 0 0 0 0 X", "com.android.tv/US_TV/US_TV_G");
-        US_RATING_MAP.put("3 0 0 0 0 0 0 X", "com.android.tv/US_TV/US_TV_PG");
-        US_RATING_MAP.put("3 1 0 0 0 0 0 X", "com.android.tv/US_TV/US_TV_PG/US_TV_D");
-        US_RATING_MAP.put("3 0 1 0 0 0 0 X", "com.android.tv/US_TV/US_TV_PG/US_TV_L");
-        US_RATING_MAP.put("3 0 0 1 0 0 0 X", "com.android.tv/US_TV/US_TV_PG/US_TV_S");
-        US_RATING_MAP.put("3 0 0 0 1 0 0 X", "com.android.tv/US_TV/US_TV_PG/US_TV_V");
-        US_RATING_MAP.put("3 1 1 0 0 0 0 X", "com.android.tv/US_TV/US_TV_PG/US_TV_D/US_TV_L");
-        US_RATING_MAP.put("3 1 0 1 0 0 0 X", "com.android.tv/US_TV/US_TV_PG/US_TV_D/US_TV_S");
-        US_RATING_MAP.put("3 1 0 0 1 0 0 X", "com.android.tv/US_TV/US_TV_PG/US_TV_D/US_TV_V");
-        US_RATING_MAP.put("3 0 1 1 0 0 0 X", "com.android.tv/US_TV/US_TV_PG/US_TV_L/US_TV_S");
-        US_RATING_MAP.put("3 0 1 0 1 0 0 X", "com.android.tv/US_TV/US_TV_PG/US_TV_L/US_TV_V");
-        US_RATING_MAP.put("3 0 0 1 1 0 0 X", "com.android.tv/US_TV/US_TV_PG/US_TV_S/US_TV_V");
-        US_RATING_MAP.put(
-                "3 1 1 1 0 0 0 X", "com.android.tv/US_TV/US_TV_PG/US_TV_D/US_TV_L/US_TV_S");
-        US_RATING_MAP.put(
-                "3 1 1 0 1 0 0 X", "com.android.tv/US_TV/US_TV_PG/US_TV_D/US_TV_L/US_TV_V");
-        US_RATING_MAP.put(
-                "3 1 0 1 1 0 0 X", "com.android.tv/US_TV/US_TV_PG/US_TV_D/US_TV_S/US_TV_V");
-        US_RATING_MAP.put(
-                "3 0 1 1 1 0 0 X", "com.android.tv/US_TV/US_TV_PG/US_TV_L/US_TV_S/US_TV_V");
-        US_RATING_MAP.put(
-                "3 1 1 1 1 0 0 X", "com.android.tv/US_TV/US_TV_PG/US_TV_D/US_TV_L/US_TV_S/US_TV_V");
-        US_RATING_MAP.put("4 0 0 0 0 0 0 X", "com.android.tv/US_TV/US_TV_14");
-        US_RATING_MAP.put("4 1 0 0 0 0 0 X", "com.android.tv/US_TV/US_TV_14/US_TV_D");
-        US_RATING_MAP.put("4 0 1 0 0 0 0 X", "com.android.tv/US_TV/US_TV_14/US_TV_L");
-        US_RATING_MAP.put("4 0 0 1 0 0 0 X", "com.android.tv/US_TV/US_TV_14/US_TV_S");
-        US_RATING_MAP.put("4 0 0 0 1 0 0 X", "com.android.tv/US_TV/US_TV_14/US_TV_V");
-        US_RATING_MAP.put("4 1 1 0 0 0 0 X", "com.android.tv/US_TV/US_TV_14/US_TV_D/US_TV_L");
-        US_RATING_MAP.put("4 1 0 1 0 0 0 X", "com.android.tv/US_TV/US_TV_14/US_TV_D/US_TV_S");
-        US_RATING_MAP.put("4 1 0 0 1 0 0 X", "com.android.tv/US_TV/US_TV_14/US_TV_D/US_TV_V");
-        US_RATING_MAP.put("4 0 1 1 0 0 0 X", "com.android.tv/US_TV/US_TV_14/US_TV_L/US_TV_S");
-        US_RATING_MAP.put("4 0 1 0 1 0 0 X", "com.android.tv/US_TV/US_TV_14/US_TV_L/US_TV_V");
-        US_RATING_MAP.put("4 0 0 1 1 0 0 X", "com.android.tv/US_TV/US_TV_14/US_TV_S/US_TV_V");
-        US_RATING_MAP.put(
-                "4 1 1 1 0 0 0 X", "com.android.tv/US_TV/US_TV_14/US_TV_D/US_TV_L/US_TV_S");
-        US_RATING_MAP.put(
-                "4 1 1 0 1 0 0 X", "com.android.tv/US_TV/US_TV_14/US_TV_D/US_TV_L/US_TV_V");
-        US_RATING_MAP.put(
-                "4 1 0 1 1 0 0 X", "com.android.tv/US_TV/US_TV_14/US_TV_D/US_TV_S/US_TV_V");
-        US_RATING_MAP.put(
-                "4 0 1 1 1 0 0 X", "com.android.tv/US_TV/US_TV_14/US_TV_L/US_TV_S/US_TV_V");
-        US_RATING_MAP.put(
-                "4 1 1 1 1 0 0 X", "com.android.tv/US_TV/US_TV_14/US_TV_D/US_TV_L/US_TV_S/US_TV_V");
-        US_RATING_MAP.put("5 0 0 0 0 0 0 X", "com.android.tv/US_TV/US_TV_MA");
-        US_RATING_MAP.put("5 0 1 0 0 0 0 X", "com.android.tv/US_TV/US_TV_MA/US_TV_L");
-        US_RATING_MAP.put("5 0 0 1 0 0 0 X", "com.android.tv/US_TV/US_TV_MA/US_TV_S");
-        US_RATING_MAP.put("5 0 0 0 1 0 0 X", "com.android.tv/US_TV/US_TV_MA/US_TV_V");
-        US_RATING_MAP.put("5 0 1 1 0 0 0 X", "com.android.tv/US_TV/US_TV_MA/US_TV_L/US_TV_S");
-        US_RATING_MAP.put("5 0 1 0 1 0 0 X", "com.android.tv/US_TV/US_TV_MA/US_TV_L/US_TV_V");
-        US_RATING_MAP.put("5 0 0 1 1 0 0 X", "com.android.tv/US_TV/US_TV_MA/US_TV_S/US_TV_V");
-        US_RATING_MAP.put(
-                "5 0 1 1 1 0 0 X", "com.android.tv/US_TV/US_TV_MA/US_TV_L/US_TV_S/US_TV_V");
-        US_RATING_MAP.put("X X X X X X X 1", ""); // MPAA-N/A
-        US_RATING_MAP.put("X X X X X X X 2", "com.android.tv/US_MV/US_MV_G");
-        US_RATING_MAP.put("X X X X X X X 3", "com.android.tv/US_MV/US_MV_PG");
-        US_RATING_MAP.put("X X X X X X X 4", "com.android.tv/US_MV/US_MV_PG13");
-        US_RATING_MAP.put("X X X X X X X 5", "com.android.tv/US_MV/US_MV_R");
-        US_RATING_MAP.put("X X X X X X X 6", "com.android.tv/US_MV/US_MV_NC17");
-        // MPAA-X was replaced by NC17
-        US_RATING_MAP.put("X X X X X X X 7", "com.android.tv/US_MV/US_MV_NC17");
-        US_RATING_MAP.put("X X X X X X X 8", ""); // MPAA - Not Rated
-    }
-
-    @Test
-    public void testGenerateContentRating_emptyInput() {
-        assertThat(SectionParser.generateContentRating(new ArrayList<TsDescriptor>())).isEmpty();
-    }
-
-    @Test
-    public void testGenerateContentRating_validInputs() {
-        for (Map.Entry<String, String> entry : US_RATING_MAP.entrySet()) {
-            RatingRegion ratingRegion = createRatingRegionForTest(entry.getKey(), RATING_REGION_US);
-            ContentAdvisoryDescriptor descriptor = createDescriptorForTest(ratingRegion);
-            assertWithMessage("key = " + entry.getKey())
-                    .that(
-                            SectionParser.generateContentRating(
-                                    Collections.singletonList((TsDescriptor) descriptor)))
-                    .isEqualTo(entry.getValue());
-        }
-    }
-
-    @Test
-    public void testGenerateContentRating_invalidInput() {
-        // Invalid because the value of the first dimension is lost.
-        RatingRegion ratingRegion = createRatingRegionForTest("X 1 0 0 0 0 0 X", RATING_REGION_US);
-        ContentAdvisoryDescriptor descriptor = createDescriptorForTest(ratingRegion);
-        assertThat(
-                        SectionParser.generateContentRating(
-                                Collections.singletonList((TsDescriptor) descriptor)))
-                .isEmpty();
-    }
-
-    @Test
-    public void testGenerateContentRating_multipleRatings() {
-        // TV-MA
-        RatingRegion ratingRegionTv =
-                createRatingRegionForTest("5 0 0 0 0 0 0 X", RATING_REGION_US);
-        // MPAA-R
-        RatingRegion ratingRegionMv =
-                createRatingRegionForTest("X X X X X X X 5", RATING_REGION_US);
-        ContentAdvisoryDescriptor descriptorTv = createDescriptorForTest(ratingRegionTv);
-        ContentAdvisoryDescriptor descriptorMv = createDescriptorForTest(ratingRegionMv);
-        assertThat(
-                        SectionParser.generateContentRating(
-                                Arrays.<TsDescriptor>asList(descriptorTv, descriptorMv)))
-                .isEqualTo("com.android.tv/US_MV/US_MV_R,com.android.tv/US_TV/US_TV_MA");
-    }
-
-    private static RatingRegion createRatingRegionForTest(String values, int region) {
-        String[] valueArray = values.split(" ");
-        List<RegionalRating> regionalRatings = new ArrayList<>();
-        for (int i = 0; i < valueArray.length; i++) {
-            try {
-                int value = Integer.valueOf(valueArray[i]);
-                if (value != 0) {
-                    // value 0 means the dimension should be omitted from the descriptor
-                    regionalRatings.add(new RegionalRating(i, value));
-                }
-            } catch (NumberFormatException e) {
-                // do nothing
-            }
-        }
-        return new RatingRegion(region, "", regionalRatings);
-    }
-
-    private static ContentAdvisoryDescriptor createDescriptorForTest(RatingRegion... regions) {
-        return new ContentAdvisoryDescriptor(Arrays.asList(regions));
-    }
-}
diff --git a/tuner/tests/robotests/javatests/com/android/tv/tuner/dvb/DvbTunerHalTest.java b/tuner/tests/robotests/javatests/com/android/tv/tuner/dvb/DvbTunerHalTest.java
deleted file mode 100644
index 13fb06a..0000000
--- a/tuner/tests/robotests/javatests/com/android/tv/tuner/dvb/DvbTunerHalTest.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2018 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.dvb;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import com.android.tv.common.compat.TvInputConstantCompat;
-import com.android.tv.testing.TestSingletonApp;
-import com.android.tv.testing.constants.ConfigConstants;
-import com.android.tv.tuner.tvinput.TunerSessionWorker;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-/** Tests for {@link TunerSessionWorker}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK, application = TestSingletonApp.class)
-public class DvbTunerHalTest {
-    private int mSignal = 0;
-
-    DvbTunerHal mDvbTunerHal =
-            new DvbTunerHal(RuntimeEnvironment.application) {
-                @Override
-                protected int nativeGetSignalStrength(long deviceId) {
-                    return mSignal;
-                }
-            };
-
-    @Test
-    public void getSignalStrength_notUsed() {
-        mSignal = -3;
-        int signal = mDvbTunerHal.getSignalStrength();
-        assertThat(signal).isEqualTo(TvInputConstantCompat.SIGNAL_STRENGTH_NOT_USED);
-    }
-
-    @Test
-    public void getSignalStrength_errorMax() {
-        mSignal = Integer.MAX_VALUE;
-        int signal = mDvbTunerHal.getSignalStrength();
-        assertThat(signal).isEqualTo(TvInputConstantCompat.SIGNAL_STRENGTH_ERROR);
-    }
-
-    @Test
-    public void getSignalStrength_errorMin() {
-        mSignal = Integer.MIN_VALUE;
-        int signal = mDvbTunerHal.getSignalStrength();
-        assertThat(signal).isEqualTo(TvInputConstantCompat.SIGNAL_STRENGTH_ERROR);
-    }
-
-    @Test
-    public void getSignalStrength_error() {
-        mSignal = -1;
-        int signal = mDvbTunerHal.getSignalStrength();
-        assertThat(signal).isEqualTo(TvInputConstantCompat.SIGNAL_STRENGTH_ERROR);
-    }
-
-    @Test
-    public void getSignalStrength_curvedMax() {
-        mSignal = 65535;
-        int signal = mDvbTunerHal.getSignalStrength();
-        assertThat(signal).isEqualTo(100);
-    }
-
-    @Test
-    public void getSignalStrength_curvedHalf() {
-        mSignal = 58982;
-        int signal = mDvbTunerHal.getSignalStrength();
-        assertThat(signal).isEqualTo(50);
-    }
-
-    @Test
-    public void getSignalStrength_curvedMin() {
-        mSignal = 0;
-        int signal = mDvbTunerHal.getSignalStrength();
-        assertThat(signal).isEqualTo(0);
-    }
-}
diff --git a/tuner/tests/robotests/javatests/com/android/tv/tuner/exoplayer/tests/AssetDataSource.java b/tuner/tests/robotests/javatests/com/android/tv/tuner/exoplayer/tests/AssetDataSource.java
deleted file mode 100644
index 52faa1d..0000000
--- a/tuner/tests/robotests/javatests/com/android/tv/tuner/exoplayer/tests/AssetDataSource.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * 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.tests;
-
-import android.content.Context;
-import android.content.res.AssetManager;
-import android.net.Uri;
-import com.google.android.exoplayer.C;
-import com.google.android.exoplayer2.upstream.DataSource;
-import com.google.android.exoplayer2.upstream.DataSpec;
-import com.google.android.exoplayer2.upstream.TransferListener;
-import java.io.EOFException;
-import java.io.IOException;
-import java.io.InputStream;
-
-/** A local asset. */
-// Copied from com.google.android.exoplayer.upstream.AssetDataSource for test.
-final class AssetDataSource implements DataSource {
-    /** Thrown when an {@link IOException} is encountered reading a local asset. */
-    private static final class AssetDataSourceException extends IOException {
-        private AssetDataSourceException(IOException cause) {
-            super(cause);
-        }
-    }
-
-    private final AssetManager mAssetManager;
-
-    private InputStream mInputStream;
-    private long mBytesRemaining;
-    private Uri mUri;
-
-    /** Constructs a new {@link DataSource} that retrieves data from a local asset. */
-    AssetDataSource(Context context) {
-        mAssetManager = context.getAssets();
-    }
-
-    @Override
-    public long open(DataSpec dataSpec) throws AssetDataSourceException {
-        try {
-            String path = dataSpec.uri.getPath();
-            if (path.startsWith("/android_asset/")) {
-                path = path.substring(15);
-            } else if (path.startsWith("/")) {
-                path = path.substring(1);
-            }
-            mInputStream = mAssetManager.open(path, AssetManager.ACCESS_RANDOM);
-            long skipped = mInputStream.skip(dataSpec.position);
-            if (skipped < dataSpec.position) {
-                // mAssetManager.open() returns an AssetInputStream, whose skip() implementation
-                // only skips fewer bytes than requested if the skip is beyond the end of the
-                // asset's data.
-                throw new EOFException();
-            }
-            if (dataSpec.length != C.LENGTH_UNBOUNDED) {
-                mBytesRemaining = dataSpec.length;
-            } else {
-                mBytesRemaining = mInputStream.available();
-                if (mBytesRemaining == Integer.MAX_VALUE) {
-                    // mAssetManager.open() returns an AssetInputStream, whose available()
-                    // implementation returns Integer.MAX_VALUE if the remaining length is greater
-                    // than (or equal to) Integer.MAX_VALUE. We don't know the true length in this
-                    // case, so treat as unbounded.
-                    mBytesRemaining = C.LENGTH_UNBOUNDED;
-                }
-            }
-        } catch (IOException e) {
-            throw new AssetDataSourceException(e);
-        }
-
-        mUri = dataSpec.uri;
-        return mBytesRemaining;
-    }
-
-    @Override
-    public int read(byte[] buffer, int offset, int readLength) throws AssetDataSourceException {
-        if (mBytesRemaining == 0) {
-            return -1;
-        } else {
-            int bytesRead = 0;
-            try {
-                int bytesToRead =
-                        mBytesRemaining == C.LENGTH_UNBOUNDED
-                                ? readLength
-                                : (int) Math.min(mBytesRemaining, readLength);
-                bytesRead = mInputStream.read(buffer, offset, bytesToRead);
-            } catch (IOException e) {
-                throw new AssetDataSourceException(e);
-            }
-
-            if (bytesRead > 0 && mBytesRemaining != C.LENGTH_UNBOUNDED) {
-                mBytesRemaining -= bytesRead;
-            }
-
-            return bytesRead;
-        }
-    }
-
-    @Override
-    public void close() throws AssetDataSourceException {
-        mUri = null;
-        if (mInputStream != null) {
-            try {
-                mInputStream.close();
-            } catch (IOException e) {
-                throw new AssetDataSourceException(e);
-            } finally {
-                mInputStream = null;
-            }
-        }
-    }
-
-    @Override
-    public void addTransferListener(TransferListener transferListener) {
-        // TODO: Implement to support metrics collection.
-    }
-
-    @Override
-    public Uri getUri() {
-        return mUri;
-    }
-}
diff --git a/tuner/tests/robotests/javatests/com/android/tv/tuner/exoplayer/tests/SampleSourceExtractorTest.java b/tuner/tests/robotests/javatests/com/android/tv/tuner/exoplayer/tests/SampleSourceExtractorTest.java
deleted file mode 100644
index 5af30b9..0000000
--- a/tuner/tests/robotests/javatests/com/android/tv/tuner/exoplayer/tests/SampleSourceExtractorTest.java
+++ /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.
- */
-package com.android.tv.tuner.exoplayer.tests;
-
-import static com.google.common.truth.Truth.assertWithMessage;
-
-import static junit.framework.Assert.fail;
-
-import android.content.Context;
-import android.net.Uri;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.util.Pair;
-
-import com.android.tv.testing.constants.ConfigConstants;
-import com.android.tv.tuner.exoplayer.ExoPlayerSampleExtractor;
-import com.android.tv.tuner.exoplayer.buffer.BufferManager;
-import com.android.tv.tuner.exoplayer.buffer.BufferManager.StorageManager;
-import com.android.tv.tuner.exoplayer.buffer.PlaybackBufferListener;
-import com.android.tv.tuner.exoplayer.buffer.SampleChunk;
-import com.android.tv.tuner.testing.buffer.VerySlowSampleChunk;
-
-import com.google.android.exoplayer.MediaFormat;
-import com.google.android.exoplayer.SampleHolder;
-import com.google.android.exoplayer.SampleSource;
-import com.google.android.exoplayer2.upstream.DataSource;
-
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.Shadows;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowLooper;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.SortedMap;
-
-/** Tests for {@link ExoPlayerSampleExtractor} */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-public class SampleSourceExtractorTest {
-    // Maximum bandwidth of 1080p channel is about 2.2MB/s. 2MB for a sample will suffice.
-    private static final int SAMPLE_BUFFER_SIZE = 1024 * 1024 * 2;
-    private static final int CONSUMING_SAMPLES_PERIOD = 100;
-    private Uri testStreamUri;
-    private HandlerThread handlerThread;
-    private DataSource dataSource;
-
-    @Before
-    public void setUp() {
-        testStreamUri = Uri.parse("asset:///capture_stream.ts");
-        handlerThread = new HandlerThread("test");
-        dataSource = new AssetDataSource(RuntimeEnvironment.application);
-    }
-
-    @Test
-    public void testTrickplayDisabled() throws Throwable {
-        DataSource source = new AssetDataSource(RuntimeEnvironment.application);
-        MockPlaybackBufferListener listener = new MockPlaybackBufferListener();
-        ExoPlayerSampleExtractor extractor =
-                new ExoPlayerSampleExtractor(
-                        testStreamUri,
-                        source,
-                        null,
-                        listener,
-                        false,
-                        Looper.getMainLooper(),
-                        handlerThread,
-                        (bufferManager, bufferListener, enableTrickplay, bufferReason) -> null);
-        assertWithMessage("Trickplay should be disabled").that(listener.getLastState()).isFalse();
-        // Prepares the extractor.
-        extractor.prepare();
-        // Looper is nat available until prepare is called at least once
-        Looper handlerLooper = handlerThread.getLooper();
-        try {
-            while (!extractor.prepare()) {
-
-                ShadowLooper.getShadowMainLooper().runOneTask();
-                Shadows.shadowOf(handlerLooper).runOneTask();
-            }
-        } catch (IOException e) {
-            fail("Exception occurred while preparing: " + e.getMessage());
-        }
-        // Selects all tracks.
-        List<MediaFormat> trackFormats = extractor.getTrackFormats();
-        for (int i = 0; i < trackFormats.size(); ++i) {
-            extractor.selectTrack(i);
-        }
-        // Consumes over some period.
-        SampleHolder sampleHolder = new SampleHolder(SampleHolder.BUFFER_REPLACEMENT_MODE_NORMAL);
-        sampleHolder.ensureSpaceForWrite(SAMPLE_BUFFER_SIZE);
-
-        Shadows.shadowOf(handlerLooper).idle();
-        for (int i = 0; i < CONSUMING_SAMPLES_PERIOD; ++i) {
-            boolean found = false;
-            while (!found) {
-                for (int j = 0; j < trackFormats.size(); ++j) {
-                    int result = extractor.readSample(j, sampleHolder);
-                    switch (result) {
-                        case SampleSource.SAMPLE_READ:
-                            found = true;
-                            break;
-                        case SampleSource.END_OF_STREAM:
-                            fail("Failed to read samples");
-                            break;
-                        default:
-                    }
-                    if (found) {
-                        break;
-                    }
-                }
-                Shadows.shadowOf(handlerLooper).runOneTask();
-                ShadowLooper.getShadowMainLooper().runOneTask();
-            }
-        }
-        extractor.release();
-    }
-
-    @Ignore("b/70338667")
-    @Test
-    public void testDiskTooSlowTrickplayDisabled() throws Throwable {
-        StorageManager storageManager = new StubStorageManager(RuntimeEnvironment.application);
-        BufferManager bufferManager =
-                new BufferManager(
-                        storageManager, new VerySlowSampleChunk.VerySlowSampleChunkCreator());
-        bufferManager.setMinimumSampleSizeForSpeedCheck(0);
-        MockPlaybackBufferListener listener = new MockPlaybackBufferListener();
-        ExoPlayerSampleExtractor extractor =
-                new ExoPlayerSampleExtractor(
-                        testStreamUri,
-                        dataSource,
-                        bufferManager,
-                        listener,
-                        false,
-                        Looper.getMainLooper(),
-                        handlerThread,
-                        (bufferManager2, bufferListener, enableTrickplay, bufferReason) -> null);
-
-        assertWithMessage("Trickplay should be enabled at the first")
-                .that(Boolean.TRUE)
-                .isEqualTo(listener.getLastState());
-        // Prepares the extractor.
-        extractor.prepare();
-        // Looper is nat available until prepare is called at least once
-        Looper handlerLooper = handlerThread.getLooper();
-        try {
-            while (!extractor.prepare()) {
-
-                ShadowLooper.getShadowMainLooper().runOneTask();
-                Shadows.shadowOf(handlerLooper).runOneTask();
-            }
-        } catch (IOException e) {
-            fail("Exception occurred while preparing: " + e.getMessage());
-        }
-        // Selects all tracks.
-        List<MediaFormat> trackFormats = extractor.getTrackFormats();
-        for (int i = 0; i < trackFormats.size(); ++i) {
-            extractor.selectTrack(i);
-        }
-        // Consumes until once speed check is done.
-        SampleHolder sampleHolder = new SampleHolder(SampleHolder.BUFFER_REPLACEMENT_MODE_NORMAL);
-        sampleHolder.ensureSpaceForWrite(SAMPLE_BUFFER_SIZE);
-        while (!bufferManager.hasSpeedCheckDone()) {
-            boolean found = false;
-            while (!found) {
-                for (int j = 0; j < trackFormats.size(); ++j) {
-                    int result = extractor.readSample(j, sampleHolder);
-                    switch (result) {
-                        case SampleSource.SAMPLE_READ:
-                            found = true;
-                            break;
-                        case SampleSource.END_OF_STREAM:
-                            fail("Failed to read samples");
-                            break;
-                        default:
-                    }
-                    if (found) {
-                        break;
-                    }
-                }
-                ShadowLooper.getShadowMainLooper().runOneTask();
-                Shadows.shadowOf(handlerLooper).runOneTask();
-            }
-        }
-        extractor.release();
-        ShadowLooper.getShadowMainLooper().idle();
-        Shadows.shadowOf(handlerLooper).idle();
-        assertWithMessage("Disk too slow event should be reported")
-                .that(listener.isReportedDiskTooSlow())
-                .isTrue();
-    }
-
-    private static class StubStorageManager implements StorageManager {
-        private final Context mContext;
-
-        StubStorageManager(Context context) {
-            mContext = context;
-        }
-
-        @Override
-        public File getBufferDir() {
-            return mContext.getCacheDir();
-        }
-
-        @Override
-        public boolean isPersistent() {
-            return false;
-        }
-
-        @Override
-        public boolean reachedStorageMax(long bufferSize, long pendingDelete) {
-            return false;
-        }
-
-        @Override
-        public boolean hasEnoughBuffer(long pendingDelete) {
-            return true;
-        }
-
-        @Override
-        public List<BufferManager.TrackFormat> readTrackInfoFiles(boolean isAudio) {
-            return null;
-        }
-
-        @Override
-        public ArrayList<BufferManager.PositionHolder> readIndexFile(String trackId)
-                throws IOException {
-            return null;
-        }
-
-        @Override
-        public void writeTrackInfoFiles(List<BufferManager.TrackFormat> formatList, boolean isAudio)
-                throws IOException {
-            // No-op.
-        }
-
-        @Override
-        public void writeIndexFile(
-                String trackName, SortedMap<Long, Pair<SampleChunk, Integer>> index)
-                throws IOException {
-            // No-op.
-        }
-
-        @Override
-        public void updateIndexFile(
-                String trackName, int size, long position, SampleChunk sampleChunk, int offset)
-                throws IOException {
-            // No-op
-        }
-    }
-
-    public static class MockPlaybackBufferListener implements PlaybackBufferListener {
-        private Boolean mLastState;
-        private boolean mIsReportedDiskTooSlow;
-
-        public Boolean getLastState() {
-            return mLastState;
-        }
-
-        public boolean isReportedDiskTooSlow() {
-            return mIsReportedDiskTooSlow;
-        }
-        // PlaybackBufferListener
-        @Override
-        public void onBufferStartTimeChanged(long startTimeMs) {
-            // No-op.
-        }
-
-        @Override
-        public void onBufferStateChanged(boolean available) {
-            mLastState = available;
-        }
-
-        @Override
-        public void onDiskTooSlow() {
-            mIsReportedDiskTooSlow = true;
-        }
-    }
-}
diff --git a/tuner/tests/robotests/javatests/com/android/tv/tuner/testing/TvTunerRobolectricTestRunner.java b/tuner/tests/robotests/javatests/com/android/tv/tuner/testing/TvTunerRobolectricTestRunner.java
deleted file mode 100644
index 31dc25d..0000000
--- a/tuner/tests/robotests/javatests/com/android/tv/tuner/testing/TvTunerRobolectricTestRunner.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2019 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.testing;
-
-import org.junit.runners.model.InitializationError;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-import org.robolectric.manifest.AndroidManifest;
-import org.robolectric.res.Fs;
-import org.robolectric.res.ResourcePath;
-
-import java.util.List;
-
-/**
- * Custom test runner TV tuner. This is needed because the default behavior for robolectric is just
- * to grab the resource directory in the target package. We want to override this to add several
- * spanning different projects.
- *
- * <p><b>Note</b> copied from
- * http://cs/android/packages/apps/Settings/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java
- */
-public class TvTunerRobolectricTestRunner extends RobolectricTestRunner {
-
-    /** We don't actually want to change this behavior, so we just call super. */
-    public TvTunerRobolectricTestRunner(Class<?> testClass) throws InitializationError {
-        super(testClass);
-    }
-
-    /**
-     * We are going to create our own custom manifest so that we can add multiple resource paths to
-     * it.
-     */
-    @Override
-    protected AndroidManifest getAppManifest(Config config) {
-        final String packageName = "com.android.tv.tuner";
-
-        // By adding any resources from libraries we need the AndroidManifest, we can access
-        // them from within the parallel universe's resource loader.
-        return new AndroidManifest(
-                Fs.fileFromPath(config.manifest()),
-                Fs.fileFromPath(config.resourceDir()),
-                Fs.fileFromPath(config.assetDir()),
-                packageName) {
-            @Override
-            public List<ResourcePath> getIncludedResourcePaths() {
-                List<ResourcePath> paths = super.getIncludedResourcePaths();
-                TvTunerRobolectricTestRunner.getIncludedResourcePaths(paths);
-                return paths;
-            }
-        };
-    }
-
-    public static void getIncludedResourcePaths(List<ResourcePath> paths) {
-	paths.add(
-                new ResourcePath(
-                        null,
-                        Fs.fileFromPath("./packages/apps/TV/tuner/res"),
-                        null));
-    }
-}
diff --git a/tuner/tests/robotests/javatests/com/android/tv/tuner/tvinput/TunerSessionWorkerExoV2Test.java b/tuner/tests/robotests/javatests/com/android/tv/tuner/tvinput/TunerSessionWorkerExoV2Test.java
deleted file mode 100644
index 24adbaa..0000000
--- a/tuner/tests/robotests/javatests/com/android/tv/tuner/tvinput/TunerSessionWorkerExoV2Test.java
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * 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.tvinput;
-
-import static com.android.tv.common.customization.CustomizationManager.TRICKPLAY_MODE_ENABLED;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.app.Application;
-import android.content.Context;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.view.accessibility.CaptioningManager;
-
-import com.android.tv.common.CommonConstants;
-import com.android.tv.common.CommonPreferences;
-import com.android.tv.common.compat.TvInputConstantCompat;
-import com.android.tv.common.customization.CustomizationManager;
-import com.android.tv.common.flags.impl.DefaultLegacyFlags;
-import com.android.tv.testing.TestSingletonApp;
-import com.android.tv.testing.constants.ConfigConstants;
-import com.android.tv.tuner.exoplayer.MpegTsPlayer;
-import com.android.tv.tuner.source.TsDataSourceManager;
-import com.android.tv.tuner.source.TunerTsStreamerManager;
-import com.android.tv.tuner.testing.TvTunerRobolectricTestRunner;
-import com.android.tv.tuner.tvinput.datamanager.ChannelDataManager;
-
-import com.google.android.exoplayer.audio.AudioCapabilities;
-
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentMatchers;
-import org.mockito.Mockito;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadow.api.Shadow;
-import org.robolectric.shadows.ShadowContextImpl;
-
-import java.lang.reflect.Field;
-
-import javax.inject.Provider;
-
-/** Tests for {@link TunerSessionWorkerExoV2}. */
-@RunWith(TvTunerRobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK, application = TestSingletonApp.class)
-public class TunerSessionWorkerExoV2Test {
-
-    private TunerSessionWorkerExoV2 tunerSessionWorker;
-    private int mSignalStrength = TvInputConstantCompat.SIGNAL_STRENGTH_UNKNOWN;
-    private MpegTsPlayer mPlayer = Mockito.mock(MpegTsPlayer.class);
-    private Handler mHandler;
-    private DefaultLegacyFlags mLegacyFlags;
-
-    @Before
-    public void setUp() throws NoSuchFieldException, IllegalAccessException {
-        Application context = RuntimeEnvironment.application;
-        mLegacyFlags = DefaultLegacyFlags.DEFAULT;
-        CaptioningManager captioningManager = Mockito.mock(CaptioningManager.class);
-
-        // TODO (b/65160115)
-        Field field = CustomizationManager.class.getDeclaredField("sCustomizationPackage");
-        field.setAccessible(true);
-        field.set(null, CommonConstants.BASE_PACKAGE + ".tuner");
-        field = CustomizationManager.class.getDeclaredField("sTrickplayMode");
-        field.setAccessible(true);
-        field.set(null, TRICKPLAY_MODE_ENABLED);
-
-        ShadowContextImpl shadowContext = Shadow.extract(context.getBaseContext());
-        shadowContext.setSystemService(Context.CAPTIONING_SERVICE, captioningManager);
-
-        CommonPreferences.initialize(context);
-        ChannelDataManager channelDataManager = new ChannelDataManager(context, "testInput");
-
-        mHandler = new Handler(Looper.getMainLooper(), null);
-
-        Provider<TunerTsStreamerManager> tsStreamerManagerProvider =
-                () -> new TunerTsStreamerManager(null);
-        TsDataSourceManager.Factory tsDataSourceManagerFactory =
-                new TsDataSourceManager.Factory(tsStreamerManagerProvider);
-
-        new TunerSessionExoV2(
-                context,
-                channelDataManager,
-                session -> {},
-                recordingSession -> Uri.parse("recordingUri"),
-                (context1, channelDataManager1, tunerSession1, tunerSessionOverlay) -> {
-                    tunerSessionWorker =
-                            new TunerSessionWorkerExoV2(
-                                    context1,
-                                    channelDataManager1,
-                                    tunerSession1,
-                                    tunerSessionOverlay,
-                                    mHandler,
-                                    mLegacyFlags,
-                                    (context2, bufferManager, bufferListener) -> null,
-                                    tsDataSourceManagerFactory) {
-                                @Override
-                                protected void notifySignal(int signal) {
-                                    mSignalStrength = signal;
-                                }
-
-                                @Override
-                                protected MpegTsPlayer createPlayer(
-                                        AudioCapabilities capabilities) {
-                                    return mPlayer;
-                                }
-                            };
-                    return tunerSessionWorker;
-                });
-    }
-
-    @Test
-    public void doSelectTrack_mPlayerIsNull() {
-        Message msg = new Message();
-        msg.what = TunerSessionWorker.MSG_SELECT_TRACK;
-        assertThat(tunerSessionWorker.handleMessage(msg)).isFalse();
-    }
-
-    @Test
-    public void doCheckSignalStrength_mPlayerIsNull() {
-        Message msg = new Message();
-        msg.what = TunerSessionWorker.MSG_CHECK_SIGNAL_STRENGTH;
-        assertThat(tunerSessionWorker.handleMessage(msg)).isFalse();
-    }
-
-    @Test
-    public void handleSignal_isNotUsed() {
-        assertThat(tunerSessionWorker.handleSignal(TvInputConstantCompat.SIGNAL_STRENGTH_NOT_USED))
-                .isTrue();
-        assertThat(mSignalStrength).isEqualTo(TvInputConstantCompat.SIGNAL_STRENGTH_NOT_USED);
-    }
-
-    @Test
-    public void handleSignal_isError() {
-        assertThat(tunerSessionWorker.handleSignal(TvInputConstantCompat.SIGNAL_STRENGTH_ERROR))
-                .isTrue();
-        assertThat(mSignalStrength).isEqualTo(TvInputConstantCompat.SIGNAL_STRENGTH_ERROR);
-    }
-
-    @Test
-    public void handleSignal_isUnknown() {
-        assertThat(tunerSessionWorker.handleSignal(TvInputConstantCompat.SIGNAL_STRENGTH_UNKNOWN))
-                .isTrue();
-        assertThat(mSignalStrength).isEqualTo(TvInputConstantCompat.SIGNAL_STRENGTH_UNKNOWN);
-    }
-
-    @Test
-    public void handleSignal_isNotifySignal() {
-        assertThat(tunerSessionWorker.handleSignal(100)).isTrue();
-        assertThat(mSignalStrength).isEqualTo(100);
-    }
-
-    @Test
-    public void preparePlayback_playerIsNotReady() {
-        Mockito.when(
-                        mPlayer.prepare(
-                                Mockito.eq(RuntimeEnvironment.application),
-                                ArgumentMatchers.any(),
-                                ArgumentMatchers.anyBoolean(),
-                                ArgumentMatchers.any()))
-                .thenReturn(false);
-        tunerSessionWorker.preparePlayback();
-        assertThat(mHandler.hasMessages(TunerSessionWorker.MSG_TUNE)).isFalse();
-        assertThat(mHandler.hasMessages(TunerSessionWorker.MSG_RETRY_PLAYBACK)).isTrue();
-        assertThat(mHandler.hasMessages(TunerSessionWorker.MSG_CHECK_SIGNAL_STRENGTH)).isFalse();
-        assertThat(mHandler.hasMessages(TunerSessionWorker.MSG_CHECK_SIGNAL)).isFalse();
-    }
-
-    @Test
-    @Ignore
-    public void preparePlayback_playerIsReady() {
-        Mockito.when(
-                        mPlayer.prepare(
-                                RuntimeEnvironment.application,
-                                ArgumentMatchers.any(),
-                                ArgumentMatchers.anyBoolean(),
-                                ArgumentMatchers.any()))
-                .thenReturn(true);
-        tunerSessionWorker.preparePlayback();
-        assertThat(mHandler.hasMessages(TunerSessionWorker.MSG_RETRY_PLAYBACK)).isFalse();
-        assertThat(mHandler.hasMessages(TunerSessionWorker.MSG_CHECK_SIGNAL_STRENGTH)).isTrue();
-        assertThat(mHandler.hasMessages(TunerSessionWorker.MSG_CHECK_SIGNAL)).isTrue();
-    }
-}
diff --git a/tuner/tests/robotests/javatests/com/android/tv/tuner/tvinput/TunerSessionWorkerTest.java b/tuner/tests/robotests/javatests/com/android/tv/tuner/tvinput/TunerSessionWorkerTest.java
deleted file mode 100644
index 536af60..0000000
--- a/tuner/tests/robotests/javatests/com/android/tv/tuner/tvinput/TunerSessionWorkerTest.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * 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.tvinput;
-
-import static com.android.tv.common.customization.CustomizationManager.TRICKPLAY_MODE_ENABLED;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.app.Application;
-import android.content.Context;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.view.accessibility.CaptioningManager;
-
-import com.android.tv.common.CommonConstants;
-import com.android.tv.common.CommonPreferences;
-import com.android.tv.common.compat.TvInputConstantCompat;
-import com.android.tv.common.customization.CustomizationManager;
-import com.android.tv.common.flags.impl.DefaultLegacyFlags;
-import com.android.tv.testing.TestSingletonApp;
-import com.android.tv.testing.constants.ConfigConstants;
-import com.android.tv.tuner.exoplayer.MpegTsPlayer;
-import com.android.tv.tuner.source.TsDataSourceManager;
-import com.android.tv.tuner.source.TunerTsStreamerManager;
-import com.android.tv.tuner.testing.TvTunerRobolectricTestRunner;
-import com.android.tv.tuner.tvinput.datamanager.ChannelDataManager;
-
-import com.google.android.exoplayer.audio.AudioCapabilities;
-
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentMatchers;
-import org.mockito.Mockito;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadow.api.Shadow;
-import org.robolectric.shadows.ShadowContextImpl;
-
-import java.lang.reflect.Field;
-
-import javax.inject.Provider;
-
-/** Tests for {@link TunerSessionWorker}. */
-@RunWith(TvTunerRobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK, application = TestSingletonApp.class)
-public class TunerSessionWorkerTest {
-
-    private TunerSessionWorker tunerSessionWorker;
-    private int mSignalStrength = TvInputConstantCompat.SIGNAL_STRENGTH_UNKNOWN;
-    private MpegTsPlayer mPlayer = Mockito.mock(MpegTsPlayer.class);
-    private Handler mHandler;
-    private DefaultLegacyFlags mLegacyFlags;
-
-    @Before
-    public void setUp() throws NoSuchFieldException, IllegalAccessException {
-        Application context = RuntimeEnvironment.application;
-        CaptioningManager captioningManager = Mockito.mock(CaptioningManager.class);
-        mLegacyFlags = DefaultLegacyFlags.DEFAULT;
-
-        // TODO (b/65160115)
-        Field field = CustomizationManager.class.getDeclaredField("sCustomizationPackage");
-        field.setAccessible(true);
-        field.set(null, CommonConstants.BASE_PACKAGE + ".tuner");
-        field = CustomizationManager.class.getDeclaredField("sTrickplayMode");
-        field.setAccessible(true);
-        field.set(null, TRICKPLAY_MODE_ENABLED);
-
-        ShadowContextImpl shadowContext = Shadow.extract(context.getBaseContext());
-        shadowContext.setSystemService(Context.CAPTIONING_SERVICE, captioningManager);
-
-        CommonPreferences.initialize(context);
-        ChannelDataManager channelDataManager = new ChannelDataManager(context, "testInput");
-
-        mHandler = new Handler(Looper.getMainLooper(), null);
-        Provider<TunerTsStreamerManager> tsStreamerManagerProvider =
-                () -> new TunerTsStreamerManager(null);
-        TsDataSourceManager.Factory tsdm =
-                new TsDataSourceManager.Factory(tsStreamerManagerProvider);
-
-        new TunerSession(
-                context,
-                channelDataManager,
-                session -> {},
-                recordingSession -> Uri.parse("recordingUri"),
-                (context1, channelDataManager1, tunerSession1, tunerSessionOverlay) -> {
-                    tunerSessionWorker =
-                            new TunerSessionWorker(
-                                    context1,
-                                    channelDataManager1,
-                                    tunerSession1,
-                                    new TunerSessionOverlay(context1),
-                                    mHandler,
-                                    mLegacyFlags,
-                                    (context2, bufferManager, bufferListener) -> null,
-                                    tsdm) {
-                                @Override
-                                protected void notifySignal(int signal) {
-                                    mSignalStrength = signal;
-                                }
-
-                                @Override
-                                protected MpegTsPlayer createPlayer(
-                                        AudioCapabilities capabilities) {
-                                    return mPlayer;
-                                }
-                            };
-                    return tunerSessionWorker;
-                });
-    }
-
-    @Test
-    public void doSelectTrack_mPlayerIsNull() {
-        Message msg = new Message();
-        msg.what = TunerSessionWorker.MSG_SELECT_TRACK;
-        assertThat(tunerSessionWorker.handleMessage(msg)).isFalse();
-    }
-
-    @Test
-    public void doCheckSignalStrength_mPlayerIsNull() {
-        Message msg = new Message();
-        msg.what = TunerSessionWorker.MSG_CHECK_SIGNAL_STRENGTH;
-        assertThat(tunerSessionWorker.handleMessage(msg)).isFalse();
-    }
-
-    @Test
-    public void handleSignal_isNotUsed() {
-        assertThat(tunerSessionWorker.handleSignal(TvInputConstantCompat.SIGNAL_STRENGTH_NOT_USED))
-                .isTrue();
-        assertThat(mSignalStrength).isEqualTo(TvInputConstantCompat.SIGNAL_STRENGTH_NOT_USED);
-    }
-
-    @Test
-    public void handleSignal_isError() {
-        assertThat(tunerSessionWorker.handleSignal(TvInputConstantCompat.SIGNAL_STRENGTH_ERROR))
-                .isTrue();
-        assertThat(mSignalStrength).isEqualTo(TvInputConstantCompat.SIGNAL_STRENGTH_ERROR);
-    }
-
-    @Test
-    public void handleSignal_isUnknown() {
-        assertThat(tunerSessionWorker.handleSignal(TvInputConstantCompat.SIGNAL_STRENGTH_UNKNOWN))
-                .isTrue();
-        assertThat(mSignalStrength).isEqualTo(TvInputConstantCompat.SIGNAL_STRENGTH_UNKNOWN);
-    }
-
-    @Test
-    public void handleSignal_isNotifySignal() {
-        assertThat(tunerSessionWorker.handleSignal(100)).isTrue();
-        assertThat(mSignalStrength).isEqualTo(100);
-    }
-
-    @Test
-    public void preparePlayback_playerIsNotReady() {
-        Mockito.when(
-                        mPlayer.prepare(
-                                Mockito.eq(RuntimeEnvironment.application),
-                                ArgumentMatchers.any(),
-                                ArgumentMatchers.anyBoolean(),
-                                ArgumentMatchers.any()))
-                .thenReturn(false);
-        tunerSessionWorker.preparePlayback();
-        assertThat(mHandler.hasMessages(TunerSessionWorker.MSG_TUNE)).isFalse();
-        assertThat(mHandler.hasMessages(TunerSessionWorker.MSG_RETRY_PLAYBACK)).isTrue();
-        assertThat(mHandler.hasMessages(TunerSessionWorker.MSG_CHECK_SIGNAL_STRENGTH)).isFalse();
-        assertThat(mHandler.hasMessages(TunerSessionWorker.MSG_CHECK_SIGNAL)).isFalse();
-    }
-
-    @Test
-    @Ignore
-    public void preparePlayback_playerIsReady() {
-        Mockito.when(
-                        mPlayer.prepare(
-                                RuntimeEnvironment.application,
-                                ArgumentMatchers.any(),
-                                ArgumentMatchers.anyBoolean(),
-                                ArgumentMatchers.any()))
-                .thenReturn(true);
-        tunerSessionWorker.preparePlayback();
-        assertThat(mHandler.hasMessages(TunerSessionWorker.MSG_RETRY_PLAYBACK)).isFalse();
-        assertThat(mHandler.hasMessages(TunerSessionWorker.MSG_CHECK_SIGNAL_STRENGTH)).isTrue();
-        assertThat(mHandler.hasMessages(TunerSessionWorker.MSG_CHECK_SIGNAL)).isTrue();
-    }
-}
diff --git a/tuner/tests/robotests/javatests/com/android/tv/tuner/tvinput/datamanager/ChannelDataManagerTest.java b/tuner/tests/robotests/javatests/com/android/tv/tuner/tvinput/datamanager/ChannelDataManagerTest.java
deleted file mode 100644
index 0da76ef..0000000
--- a/tuner/tests/robotests/javatests/com/android/tv/tuner/tvinput/datamanager/ChannelDataManagerTest.java
+++ /dev/null
@@ -1,90 +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.tuner.tvinput.datamanager;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.ContentValues;
-import android.content.pm.ProviderInfo;
-import android.media.tv.TvContract;
-
-import com.android.tv.testing.TestSingletonApp;
-import com.android.tv.testing.constants.ConfigConstants;
-import com.android.tv.testing.fakes.FakeTvProvider;
-import com.android.tv.tuner.data.Channel;
-import com.android.tv.tuner.data.TunerChannel;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.Robolectric;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowContentResolver;
-import org.robolectric.shadows.ShadowContextWrapper;
-
-/** Tests for {@link com.android.tv.tuner.tvinput.datamanager.ChannelDataManager}. */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK, application = TestSingletonApp.class)
-public class ChannelDataManagerTest {
-
-    private ChannelDataManager mChannelDataManager;
-
-    @Before
-    public void setup() {
-        ProviderInfo info = new ProviderInfo();
-        info.authority = TvContract.AUTHORITY;
-        FakeTvProvider provider =
-                Robolectric.buildContentProvider(FakeTvProvider.class).create(info).get();
-        provider.setCallingPackage("com.android.tv");
-        provider.onCreate();
-        ShadowContextWrapper shadowContextWrapper = new ShadowContextWrapper();
-        shadowContextWrapper.grantPermissions(android.Manifest.permission.MODIFY_PARENTAL_CONTROLS);
-        ShadowContentResolver.registerProviderInternal(TvContract.AUTHORITY, provider);
-        provider.delete(TvContract.Channels.CONTENT_URI, null, null);
-        ContentValues contentValues = new ContentValues();
-        contentValues.put(TvContract.Channels.COLUMN_INPUT_ID, "com.android.tv");
-        contentValues.put(
-                TvContract.Channels.COLUMN_INTERNAL_PROVIDER_DATA,
-                Channel.TunerChannelProto.getDefaultInstance().toByteArray());
-        contentValues.put(TvContract.Channels.COLUMN_LOCKED, 0);
-        provider.insert(TvContract.Channels.CONTENT_URI, contentValues);
-        contentValues.put(TvContract.Channels.COLUMN_LOCKED, 1);
-        provider.insert(TvContract.Channels.CONTENT_URI, contentValues);
-
-        mChannelDataManager = new ChannelDataManager(RuntimeEnvironment.application, "testInput");
-    }
-
-    @After
-    public void tearDown() {
-        mChannelDataManager.releaseSafely();
-    }
-
-    @Test
-    public void getChannel_locked() {
-        TunerChannel tunerChannel = mChannelDataManager.getChannel(2L);
-        assertThat(tunerChannel.isLocked()).isTrue();
-    }
-
-    @Test
-    public void getChannel_unlocked() {
-        TunerChannel tunerChannel = mChannelDataManager.getChannel(1L);
-        assertThat(tunerChannel.isLocked()).isFalse();
-    }
-}
diff --git a/tuner/tests/robotests/javatests/com/android/tv/tuner/util/PostalCodeUtilsTest.java b/tuner/tests/robotests/javatests/com/android/tv/tuner/util/PostalCodeUtilsTest.java
deleted file mode 100644
index 5a49904..0000000
--- a/tuner/tests/robotests/javatests/com/android/tv/tuner/util/PostalCodeUtilsTest.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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 static com.google.common.truth.Truth.assertThat;
-
-import com.android.tv.common.util.PostalCodeUtils;
-import com.android.tv.testing.constants.ConfigConstants;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-import java.util.Locale;
-
-/** Tests for {@link PostalCodeUtils} */
-@RunWith(RobolectricTestRunner.class)
-@Config(sdk = ConfigConstants.SDK)
-public class PostalCodeUtilsTest {
-
-    private static final String[] VALID_POSTCODES_US = {"94043", "94063", "90007"};
-    private static final String[] INVALID_POSTCODES_US = {
-        "", "9404", "ABC", "BCD8", "G777", "BT777", "OXX33", "E1WW", "SW1XX", "E11W", "SW10X",
-        "GIR", "B8", "G77", "BT7", "OX33", "E1W", "SW1X"
-    };
-    private static final String[] VALID_POSTCODES_GB = {
-        "GIR", "B8", "G77", "BT7", "OX33", "E1W", "SW1X", "GIR 0AA", "GIR0AA", "B8 2NE", "PR10BJ"
-    };
-    private static final String[] INVALID_POSTCODES_GB = {
-        "", "9404", "ABC", "BCD8", "G777", "BT777", "OXX33", "E1WW", "SW1XX", "E11W", "SW10X",
-        "94043", "94063", "90007", "B8 ", "OX331D"
-    };
-
-    @Test
-    public void validPostcodesUs() {
-        for (String postcode : VALID_POSTCODES_US) {
-            assertThat(PostalCodeUtils.matches(postcode, Locale.US.getCountry())).isTrue();
-        }
-    }
-
-    @Test
-    public void validPostcodesGb() {
-        for (String postcode : VALID_POSTCODES_GB) {
-            assertThat(PostalCodeUtils.matches(postcode, Locale.UK.getCountry())).isTrue();
-        }
-    }
-
-    @Test
-    public void invalidPostcodesUs() {
-        for (String postcode : INVALID_POSTCODES_US) {
-            assertThat(PostalCodeUtils.matches(postcode, Locale.US.getCountry())).isFalse();
-        }
-    }
-
-    @Test
-    public void invalidPostcodesGb() {
-        for (String postcode : INVALID_POSTCODES_GB) {
-            assertThat(PostalCodeUtils.matches(postcode, Locale.UK.getCountry())).isFalse();
-        }
-    }
-
-    @Test
-    public void unsupportedRegion() {
-        for (String postcode : INVALID_POSTCODES_US) {
-            // {@link Locale.ROOT} is an empty Locale
-            assertThat(PostalCodeUtils.matches(postcode, Locale.ROOT.getCountry())).isTrue();
-        }
-    }
-}
diff --git a/tuner/tests/testing/Android.mk b/tuner/tests/testing/Android.mk
index 864f5f3..79e35e5 100644
--- a/tuner/tests/testing/Android.mk
+++ b/tuner/tests/testing/Android.mk
@@ -10,7 +10,7 @@
     android-support-annotations \
     androidx.test.runner \
     tv-guava-android-jar \
-    mockito-robolectric-prebuilt \
+    mockito-target \
     tv-lib-truth \
     ub-uiautomator \
 
diff --git a/tuner/tests/testing/AndroidManifest.xml b/tuner/tests/testing/AndroidManifest.xml
index 9fcecf9..7e07a52 100644
--- a/tuner/tests/testing/AndroidManifest.xml
+++ b/tuner/tests/testing/AndroidManifest.xml
@@ -18,6 +18,6 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="com.android.tv.tuner.testing"
           android:versionCode="1">
-  <uses-sdk android:targetSdkVersion="28" android:minSdkVersion="23"/>
+  <uses-sdk android:targetSdkVersion="27" android:minSdkVersion="23"/>
     <application />
 </manifest>
diff --git a/tuner/tests/unittests/javatests/AndroidManifest.xml b/tuner/tests/unittests/javatests/AndroidManifest.xml
index ddbddd0..62caefa 100644
--- a/tuner/tests/unittests/javatests/AndroidManifest.xml
+++ b/tuner/tests/unittests/javatests/AndroidManifest.xml
@@ -18,7 +18,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="com.android.tv.tuner.layout.tests" >
 
-    <uses-sdk android:minSdkVersion="23" android:targetSdkVersion="28"/>
+    <uses-sdk android:minSdkVersion="23" android:targetSdkVersion="27"/>
 
     <instrumentation
         android:name="android.test.InstrumentationTestRunner"
diff --git a/tuner/tests/unittests/javatests/com/android/tv/tuner/AndroidManifest.xml b/tuner/tests/unittests/javatests/com/android/tv/tuner/AndroidManifest.xml
index 6956426..6fe0b85 100644
--- a/tuner/tests/unittests/javatests/com/android/tv/tuner/AndroidManifest.xml
+++ b/tuner/tests/unittests/javatests/com/android/tv/tuner/AndroidManifest.xml
@@ -18,11 +18,11 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.tv.tuner.tests" >
 
-    <uses-sdk android:minSdkVersion="23" android:targetSdkVersion="28" />
+    <uses-sdk android:minSdkVersion="23" android:targetSdkVersion="27" />
 
     <instrumentation
         android:name="androidx.test.runner.AndroidJUnitRunner"
-        android:targetPackage="com.android.tv.tuner.sample.dvb" />
+        android:targetPackage="com.android.tv" />
 
     <application android:label="TunerTvInputTests" >
         <uses-library android:name="android.test.runner" />
diff --git a/tuner/tests/unittests/javatests/com/android/tv/tuner/ZappingTimeTest.java b/tuner/tests/unittests/javatests/com/android/tv/tuner/ZappingTimeTest.java
index 031cec5..ef653f8 100644
--- a/tuner/tests/unittests/javatests/com/android/tv/tuner/ZappingTimeTest.java
+++ b/tuner/tests/unittests/javatests/com/android/tv/tuner/ZappingTimeTest.java
@@ -21,34 +21,24 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Message;
-import android.support.annotation.Nullable;
 import android.test.InstrumentationTestCase;
 import android.util.Log;
 import android.view.Surface;
-
 import androidx.test.filters.LargeTest;
-
+import com.android.tv.common.flags.impl.DefaultConcurrentDvrPlaybackFlags;
 import com.android.tv.tuner.data.Cea708Data;
-import com.android.tv.tuner.data.Channel.AudioStreamType;
-import com.android.tv.tuner.data.Channel.VideoStreamType;
 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.Channel;
 import com.android.tv.tuner.exoplayer.MpegTsPlayer;
 import com.android.tv.tuner.exoplayer.MpegTsRendererBuilder;
-import com.android.tv.tuner.exoplayer.MpegTsSampleExtractor;
 import com.android.tv.tuner.exoplayer.buffer.BufferManager;
 import com.android.tv.tuner.exoplayer.buffer.PlaybackBufferListener;
 import com.android.tv.tuner.exoplayer.buffer.TrickplayStorageManager;
 import com.android.tv.tuner.source.TsDataSourceManager;
-import com.android.tv.tuner.source.TsDataSourceManager.Factory;
 import com.android.tv.tuner.ts.EventDetector.EventListener;
-
 import com.google.android.exoplayer.ExoPlayer;
-import com.google.android.exoplayer2.upstream.DataSource;
-
-import org.junit.Ignore;
-
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -59,6 +49,7 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicLong;
+import org.junit.Ignore;
 
 /** This class use {@link FileTunerHal} to simulate tunerhal's actions to test zapping time. */
 @LargeTest
@@ -97,6 +88,8 @@
     private MockMpegTsPlayerListener mMpegTsPlayerListener = new MockMpegTsPlayerListener();
     private MockPlaybackBufferListener mPlaybackBufferListener = new MockPlaybackBufferListener();
     private MockChannelScanListener mEventListener = new MockChannelScanListener();
+    private DefaultConcurrentDvrPlaybackFlags mConcurrentDvrPlaybackFlags =
+            new DefaultConcurrentDvrPlaybackFlags();
 
     @Override
     protected void setUp() throws Exception {
@@ -106,10 +99,10 @@
         HandlerThread handlerThread = new HandlerThread(TAG);
         handlerThread.start();
         List<PsiData.PmtItem> pmtItems = new ArrayList<>();
-        pmtItems.add(new PsiData.PmtItem(VideoStreamType.MPEG2_VALUE, VIDEO_PID, null, null));
+        pmtItems.add(new PsiData.PmtItem(Channel.VideoStreamType.MPEG2, VIDEO_PID, null, null));
         for (int audioPid : AUDIO_PIDS) {
             pmtItems.add(
-                    new PsiData.PmtItem(AudioStreamType.A52AC3AUDIO_VALUE, audioPid, null, null));
+                    new PsiData.PmtItem(Channel.AudioStreamType.A52AC3AUDIO, audioPid, null, null));
         }
 
         Context context = getInstrumentation().getContext();
@@ -124,25 +117,8 @@
         mChannel.setModulation(MODULATION);
         mTunerHal = new FileTunerHal(context, tsCacheFile);
         mTunerHal.openFirstAvailable();
-        TsDataSourceManager.Factory tsFactory = new Factory(null);
-        mSourceManager = tsFactory.create(false);
+        mSourceManager = TsDataSourceManager.createSourceManager(false);
         mSourceManager.addTunerHalForTest(mTunerHal);
-        MpegTsSampleExtractor.Factory mpegTsSampleExtractorFactory =
-                new MpegTsSampleExtractor.Factory() {
-                    @Override
-                    public MpegTsSampleExtractor create(
-                            BufferManager bufferManager, PlaybackBufferListener bufferListener) {
-                        return null;
-                    }
-
-                    @Override
-                    public MpegTsSampleExtractor create(
-                            DataSource source,
-                            @Nullable BufferManager bufferManager,
-                            PlaybackBufferListener bufferListener) {
-                        return null;
-                    }
-                };
         mHandler =
                 new Handler(
                         handlerThread.getLooper(),
@@ -174,14 +150,13 @@
                                             }
                                             mChannel.setFrequency(frequency);
                                             mSourceManager.setKeepTuneStatus(true);
-
                                             mPlayer =
                                                     new MpegTsPlayer(
                                                             new MpegTsRendererBuilder(
                                                                     mTargetContext,
                                                                     bufferManager,
                                                                     mPlaybackBufferListener,
-                                                                    mpegTsSampleExtractorFactory),
+                                                                    mConcurrentDvrPlaybackFlags),
                                                             mHandler,
                                                             mSourceManager,
                                                             null,
diff --git a/tuner/tests/unittests/javatests/com/android/tv/tuner/layout/tests/AndroidManifest.xml b/tuner/tests/unittests/javatests/com/android/tv/tuner/layout/tests/AndroidManifest.xml
index 79b0987..77c7f40 100644
--- a/tuner/tests/unittests/javatests/com/android/tv/tuner/layout/tests/AndroidManifest.xml
+++ b/tuner/tests/unittests/javatests/com/android/tv/tuner/layout/tests/AndroidManifest.xml
@@ -17,7 +17,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.tv.tuner"
     android:versionCode="1">
-  <uses-sdk android:targetSdkVersion="28" android:minSdkVersion="23"/>
+  <uses-sdk android:targetSdkVersion="27" android:minSdkVersion="23"/>
   <application android:label="TunerTvInputLayoutTests" >
     <activity android:name="com.android.tv.tuner.layout.tests.ScaledLayoutActivity"
               android:label="ScaledLayout Test" />
diff --git a/tuner/tests/unittests/javatests/com/android/tv/tuner/setup/AndroidManifest.xml b/tuner/tests/unittests/javatests/com/android/tv/tuner/setup/AndroidManifest.xml
deleted file mode 100644
index 19cc0e5..0000000
--- a/tuner/tests/unittests/javatests/com/android/tv/tuner/setup/AndroidManifest.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2019 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.
-  -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.tv.tuner.setup.tests" >
-
-    <uses-sdk android:minSdkVersion="23" android:targetSdkVersion="28" />
-
-    <instrumentation
-        android:name="androidx.test.runner.AndroidJUnitRunner"
-        android:targetPackage="com.android.tv.tuner.sample.dvb" />
-
-    <application android:label="TunerTvInputTests" >
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-</manifest>
diff --git a/tuner/tests/unittests/javatests/com/android/tv/tuner/setup/TunerHalCreatorTest.java b/tuner/tests/unittests/javatests/com/android/tv/tuner/setup/TunerHalCreatorTest.java
index cc5e5c5..a3a3208 100644
--- a/tuner/tests/unittests/javatests/com/android/tv/tuner/setup/TunerHalCreatorTest.java
+++ b/tuner/tests/unittests/javatests/com/android/tv/tuner/setup/TunerHalCreatorTest.java
@@ -21,18 +21,14 @@
 import static org.junit.Assert.assertSame;
 
 import android.os.AsyncTask;
-
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
-
 import com.android.tv.tuner.api.Tuner;
 import com.android.tv.tuner.setup.BaseTunerSetupActivity.TunerHalCreator;
-
+import java.util.concurrent.Executor;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import java.util.concurrent.Executor;
-
 /** Tests for {@link TunerHalCreator}. */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
@@ -41,7 +37,7 @@
 
     private static class TestTunerHalCreator extends TunerHalCreator {
         private TestTunerHalCreator(Executor executor) {
-            super(null, executor, null);
+            super(null, executor);
         }
 
         @Override