1816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko/*
2816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Copyright (C) 2015 The Android Open Source Project
3816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko *
4816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Licensed under the Apache License, Version 2.0 (the "License");
5816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * you may not use this file except in compliance with the License.
6816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * You may obtain a copy of the License at
7816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko *
8816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko *      http://www.apache.org/licenses/LICENSE-2.0
9816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko *
10816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Unless required by applicable law or agreed to in writing, software
11816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * distributed under the License is distributed on an "AS IS" BASIS,
12816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * See the License for the specific language governing permissions and
14816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * limitations under the License.
15816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */
16816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
17816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkopackage com.android.tv;
18816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
192e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalkoimport android.annotation.TargetApi;
207d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport android.app.Activity;
211abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport android.content.ComponentName;
22816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.content.Context;
23816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.content.Intent;
2465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.content.SharedPreferences;
25816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.content.pm.PackageInfo;
26816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.content.pm.PackageManager;
27633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalkoimport android.media.tv.TvContract;
28816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.media.tv.TvInputInfo;
29816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.media.tv.TvInputManager;
301abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport android.media.tv.TvInputManager.TvInputCallback;
312e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalkoimport android.os.Build;
32816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.os.Bundle;
331abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport android.support.annotation.Nullable;
3465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.text.TextUtils;
35816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.util.Log;
36816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.view.KeyEvent;
37944779887775bd950cf1abf348d2df461593f6abLive Channels Teamimport com.android.tv.common.BaseApplication;
380645b17e2818b69b996da48fd93731bc8a01f114Live Channels Teamimport com.android.tv.common.concurrent.NamedThreadFactory;
39ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport com.android.tv.common.feature.CommonFeatures;
40944779887775bd950cf1abf348d2df461593f6abLive Channels Teamimport com.android.tv.common.recording.RecordingStorageStatusManager;
41ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport com.android.tv.common.ui.setup.animation.SetupAnimationHelper;
42944779887775bd950cf1abf348d2df461593f6abLive Channels Teamimport com.android.tv.common.util.Clock;
43944779887775bd950cf1abf348d2df461593f6abLive Channels Teamimport com.android.tv.common.util.Debug;
44944779887775bd950cf1abf348d2df461593f6abLive Channels Teamimport com.android.tv.common.util.SharedPreferencesUtils;
457d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport com.android.tv.data.ChannelDataManager;
46633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalkoimport com.android.tv.data.PreviewDataManager;
477d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport com.android.tv.data.ProgramDataManager;
48633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalkoimport com.android.tv.data.epg.EpgFetcher;
49944779887775bd950cf1abf348d2df461593f6abLive Channels Teamimport com.android.tv.data.epg.EpgFetcherImpl;
501abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.android.tv.dvr.DvrDataManager;
511abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.android.tv.dvr.DvrDataManagerImpl;
521abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.android.tv.dvr.DvrManager;
5365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.android.tv.dvr.DvrScheduleManager;
54d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport com.android.tv.dvr.DvrStorageStatusManager;
5565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.android.tv.dvr.DvrWatchedPositionManager;
56633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalkoimport com.android.tv.dvr.recorder.RecordingScheduler;
577eb2f57e74b3681dfe1c7089dc41963c0f61db7dnchalkoimport com.android.tv.dvr.ui.browse.DvrBrowseActivity;
58633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalkoimport com.android.tv.recommendation.ChannelPreviewUpdater;
59633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalkoimport com.android.tv.recommendation.RecordedProgramPreviewUpdater;
60633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalkoimport com.android.tv.tuner.TunerInputController;
6165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.android.tv.tuner.util.TunerInputInfoUtils;
621abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.android.tv.util.SetupUtils;
6307b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalkoimport com.android.tv.util.TvInputManagerHelper;
64816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport com.android.tv.util.Utils;
65816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport java.util.List;
660645b17e2818b69b996da48fd93731bc8a01f114Live Channels Teamimport java.util.concurrent.Executor;
670645b17e2818b69b996da48fd93731bc8a01f114Live Channels Teamimport java.util.concurrent.ExecutorService;
680645b17e2818b69b996da48fd93731bc8a01f114Live Channels Teamimport java.util.concurrent.Executors;
69816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
70944779887775bd950cf1abf348d2df461593f6abLive Channels Team/**
71944779887775bd950cf1abf348d2df461593f6abLive Channels Team * Live TV application.
72944779887775bd950cf1abf348d2df461593f6abLive Channels Team *
73944779887775bd950cf1abf348d2df461593f6abLive Channels Team * <p>This includes all the Google specific hooks.
74944779887775bd950cf1abf348d2df461593f6abLive Channels Team */
75944779887775bd950cf1abf348d2df461593f6abLive Channels Teampublic abstract class TvApplication extends BaseApplication implements TvSingletons, Starter {
76816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private static final String TAG = "TvApplication";
77816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private static final boolean DEBUG = false;
78633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko
79944779887775bd950cf1abf348d2df461593f6abLive Channels Team    /** Namespace for LiveChannels configs. LiveChannels configs are kept in piper. */
80944779887775bd950cf1abf348d2df461593f6abLive Channels Team    public static final String CONFIGNS_P4 = "configns:p4";
81816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
821abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    /**
8395961816a768da387f0b5523cf4363ace2044089Nick Chalko     * Broadcast Action: The user has updated LC to a new version that supports tuner input. {@link
84a1589bd48e05abbee991e0cdd27fa402a5dc5001Live Channels Team     * TunerInputController} will receive this intent to check the existence of tuner input when the
85a1589bd48e05abbee991e0cdd27fa402a5dc5001Live Channels Team     * new version is first launched.
861abddd9f6225298066094e20a6c29061b6af4590Nick Chalko     */
8765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    public static final String ACTION_APPLICATION_FIRST_LAUNCHED =
88a1589bd48e05abbee991e0cdd27fa402a5dc5001Live Channels Team            " com.android.tv.action.APPLICATION_FIRST_LAUNCHED";
8995961816a768da387f0b5523cf4363ace2044089Nick Chalko
9065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private static final String PREFERENCE_IS_FIRST_LAUNCH = "is_first_launch";
9165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
920645b17e2818b69b996da48fd93731bc8a01f114Live Channels Team    private static final NamedThreadFactory THREAD_FACTORY = new NamedThreadFactory("tv-app-db");
930645b17e2818b69b996da48fd93731bc8a01f114Live Channels Team    private static final ExecutorService DB_EXECUTOR =
940645b17e2818b69b996da48fd93731bc8a01f114Live Channels Team            Executors.newSingleThreadExecutor(THREAD_FACTORY);
950645b17e2818b69b996da48fd93731bc8a01f114Live Channels Team
96ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    private String mVersionName = "";
97ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko
98ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    private final MainActivityWrapper mMainActivityWrapper = new MainActivityWrapper();
991abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1007d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko    private SelectInputActivity mSelectInputActivity;
1017d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko    private ChannelDataManager mChannelDataManager;
102633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    private volatile ProgramDataManager mProgramDataManager;
103633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    private PreviewDataManager mPreviewDataManager;
1041abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private DvrManager mDvrManager;
10565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private DvrScheduleManager mDvrScheduleManager;
106ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    private DvrDataManager mDvrDataManager;
10765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private DvrWatchedPositionManager mDvrWatchedPositionManager;
108633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    private RecordingScheduler mRecordingScheduler;
109944779887775bd950cf1abf348d2df461593f6abLive Channels Team    private RecordingStorageStatusManager mDvrStorageStatusManager;
11095961816a768da387f0b5523cf4363ace2044089Nick Chalko    @Nullable private InputSessionManager mInputSessionManager;
111944779887775bd950cf1abf348d2df461593f6abLive Channels Team    // STOP-SHIP: Remove this variable when Tuner Process is split to another application.
11265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    // When this variable is null, we don't know in which process TvApplication runs.
11365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private Boolean mRunningInMainProcess;
114944779887775bd950cf1abf348d2df461593f6abLive Channels Team    private TvInputManagerHelper mTvInputManagerHelper;
115944779887775bd950cf1abf348d2df461593f6abLive Channels Team    private boolean mStarted;
116944779887775bd950cf1abf348d2df461593f6abLive Channels Team    private EpgFetcher mEpgFetcher;
117944779887775bd950cf1abf348d2df461593f6abLive Channels Team    private TunerInputController mTunerInputController;
118816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
119816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    @Override
120816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void onCreate() {
121816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        super.onCreate();
12295961816a768da387f0b5523cf4363ace2044089Nick Chalko        SharedPreferencesUtils.initialize(
12395961816a768da387f0b5523cf4363ace2044089Nick Chalko                this,
12495961816a768da387f0b5523cf4363ace2044089Nick Chalko                new Runnable() {
12595961816a768da387f0b5523cf4363ace2044089Nick Chalko                    @Override
12695961816a768da387f0b5523cf4363ace2044089Nick Chalko                    public void run() {
12795961816a768da387f0b5523cf4363ace2044089Nick Chalko                        if (mRunningInMainProcess != null && mRunningInMainProcess) {
12895961816a768da387f0b5523cf4363ace2044089Nick Chalko                            checkTunerServiceOnFirstLaunch();
12995961816a768da387f0b5523cf4363ace2044089Nick Chalko                        }
13095961816a768da387f0b5523cf4363ace2044089Nick Chalko                    }
13195961816a768da387f0b5523cf4363ace2044089Nick Chalko                });
1321abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        try {
1331abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            PackageInfo pInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
134ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            mVersionName = pInfo.versionName;
1351abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        } catch (PackageManager.NameNotFoundException e) {
136ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            Log.w(TAG, "Unable to find package '" + getPackageName() + "'.", e);
137ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            mVersionName = "";
1381abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
1391abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        Log.i(TAG, "Starting Live TV " + getVersionName());
14065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
141ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        // In SetupFragment, transitions are set in the constructor. Because the fragment can be
142ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        // created in Activity.onCreate() by the framework, SetupAnimationHelper should be
143ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        // initialized here before Activity.onCreate() is called.
144944779887775bd950cf1abf348d2df461593f6abLive Channels Team        mEpgFetcher = EpgFetcherImpl.create(this);
145ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        SetupAnimationHelper.initialize(this);
146944779887775bd950cf1abf348d2df461593f6abLive Channels Team        getTvInputManagerHelper();
147633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko
14865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        Log.i(TAG, "Started Live TV " + mVersionName);
149633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        Debug.getTimer(Debug.TAG_START_UP_TIMER).log("finish TvApplication.onCreate");
15065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
15165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
152944779887775bd950cf1abf348d2df461593f6abLive Channels Team    /** Initializes application. It is a noop if called twice. */
153944779887775bd950cf1abf348d2df461593f6abLive Channels Team    @Override
154944779887775bd950cf1abf348d2df461593f6abLive Channels Team    public void start() {
155944779887775bd950cf1abf348d2df461593f6abLive Channels Team        if (mStarted) {
15665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            return;
15765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
158944779887775bd950cf1abf348d2df461593f6abLive Channels Team        mStarted = true;
159944779887775bd950cf1abf348d2df461593f6abLive Channels Team        mRunningInMainProcess = true;
160944779887775bd950cf1abf348d2df461593f6abLive Channels Team        Debug.getTimer(Debug.TAG_START_UP_TIMER).log("start TvApplication.start");
16165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        if (mRunningInMainProcess) {
16295961816a768da387f0b5523cf4363ace2044089Nick Chalko            getTvInputManagerHelper()
16395961816a768da387f0b5523cf4363ace2044089Nick Chalko                    .addCallback(
16495961816a768da387f0b5523cf4363ace2044089Nick Chalko                            new TvInputCallback() {
16595961816a768da387f0b5523cf4363ace2044089Nick Chalko                                @Override
16695961816a768da387f0b5523cf4363ace2044089Nick Chalko                                public void onInputAdded(String inputId) {
167944779887775bd950cf1abf348d2df461593f6abLive Channels Team                                    if (TvFeatures.TUNER.isEnabled(TvApplication.this)
16895961816a768da387f0b5523cf4363ace2044089Nick Chalko                                            && TextUtils.equals(
169944779887775bd950cf1abf348d2df461593f6abLive Channels Team                                                    inputId, getEmbeddedTunerInputId())) {
17095961816a768da387f0b5523cf4363ace2044089Nick Chalko                                        TunerInputInfoUtils.updateTunerInputInfo(
17195961816a768da387f0b5523cf4363ace2044089Nick Chalko                                                TvApplication.this);
17295961816a768da387f0b5523cf4363ace2044089Nick Chalko                                    }
17395961816a768da387f0b5523cf4363ace2044089Nick Chalko                                    handleInputCountChanged();
17495961816a768da387f0b5523cf4363ace2044089Nick Chalko                                }
17595961816a768da387f0b5523cf4363ace2044089Nick Chalko
17695961816a768da387f0b5523cf4363ace2044089Nick Chalko                                @Override
17795961816a768da387f0b5523cf4363ace2044089Nick Chalko                                public void onInputRemoved(String inputId) {
17895961816a768da387f0b5523cf4363ace2044089Nick Chalko                                    handleInputCountChanged();
17995961816a768da387f0b5523cf4363ace2044089Nick Chalko                                }
18095961816a768da387f0b5523cf4363ace2044089Nick Chalko                            });
181944779887775bd950cf1abf348d2df461593f6abLive Channels Team            if (TvFeatures.TUNER.isEnabled(this)) {
18265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                // If the tuner input service is added before the app is started, we need to
18365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                // handle it here.
184633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko                TunerInputInfoUtils.updateTunerInputInfo(TvApplication.this);
18565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
18665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            if (CommonFeatures.DVR.isEnabled(this)) {
18765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                mDvrScheduleManager = new DvrScheduleManager(this);
18865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                mDvrManager = new DvrManager(this);
189633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko                mRecordingScheduler = RecordingScheduler.createScheduler(this);
190633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            }
191944779887775bd950cf1abf348d2df461593f6abLive Channels Team            mEpgFetcher.startRoutineService();
192633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
193633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko                ChannelPreviewUpdater.getInstance(this).startRoutineService();
194633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko                RecordedProgramPreviewUpdater.getInstance(this)
195633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko                        .updatePreviewDataForRecordedPrograms();
19665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
19765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
198944779887775bd950cf1abf348d2df461593f6abLive Channels Team        Debug.getTimer(Debug.TAG_START_UP_TIMER).log("finish TvApplication.start");
19965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
20065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
20165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private void checkTunerServiceOnFirstLaunch() {
20295961816a768da387f0b5523cf4363ace2044089Nick Chalko        SharedPreferences sharedPreferences =
20395961816a768da387f0b5523cf4363ace2044089Nick Chalko                this.getSharedPreferences(
20495961816a768da387f0b5523cf4363ace2044089Nick Chalko                        SharedPreferencesUtils.SHARED_PREF_FEATURES, Context.MODE_PRIVATE);
20565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        boolean isFirstLaunch = sharedPreferences.getBoolean(PREFERENCE_IS_FIRST_LAUNCH, true);
20665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        if (isFirstLaunch) {
20765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            if (DEBUG) Log.d(TAG, "Congratulations, it's the first launch!");
208944779887775bd950cf1abf348d2df461593f6abLive Channels Team            getTunerInputController()
209944779887775bd950cf1abf348d2df461593f6abLive Channels Team                    .onCheckingUsbTunerStatus(this, ACTION_APPLICATION_FIRST_LAUNCHED);
21065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            SharedPreferences.Editor editor = sharedPreferences.edit();
21165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            editor.putBoolean(PREFERENCE_IS_FIRST_LAUNCH, false);
21265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            editor.apply();
21365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
2141abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2151abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
216944779887775bd950cf1abf348d2df461593f6abLive Channels Team    @Override
217944779887775bd950cf1abf348d2df461593f6abLive Channels Team    public EpgFetcher getEpgFetcher() {
218944779887775bd950cf1abf348d2df461593f6abLive Channels Team        return mEpgFetcher;
219944779887775bd950cf1abf348d2df461593f6abLive Channels Team    }
220944779887775bd950cf1abf348d2df461593f6abLive Channels Team
221944779887775bd950cf1abf348d2df461593f6abLive Channels Team    @Override
222944779887775bd950cf1abf348d2df461593f6abLive Channels Team    public synchronized SetupUtils getSetupUtils() {
223944779887775bd950cf1abf348d2df461593f6abLive Channels Team        return SetupUtils.createForTvSingletons(this);
224944779887775bd950cf1abf348d2df461593f6abLive Channels Team    }
225944779887775bd950cf1abf348d2df461593f6abLive Channels Team
22695961816a768da387f0b5523cf4363ace2044089Nick Chalko    /** Returns the {@link DvrManager}. */
2271abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
2281abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public DvrManager getDvrManager() {
2291abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return mDvrManager;
2301abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2311abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
23295961816a768da387f0b5523cf4363ace2044089Nick Chalko    /** Returns the {@link DvrScheduleManager}. */
23365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
23465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    public DvrScheduleManager getDvrScheduleManager() {
23565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        return mDvrScheduleManager;
23665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
23765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
23895961816a768da387f0b5523cf4363ace2044089Nick Chalko    /** Returns the {@link RecordingScheduler}. */
239633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    @Override
240633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    @Nullable
241633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    public RecordingScheduler getRecordingScheduler() {
242633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        return mRecordingScheduler;
243633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    }
244633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko
24595961816a768da387f0b5523cf4363ace2044089Nick Chalko    /** Returns the {@link DvrWatchedPositionManager}. */
24665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
24765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    public DvrWatchedPositionManager getDvrWatchedPositionManager() {
24865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        if (mDvrWatchedPositionManager == null) {
24965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            mDvrWatchedPositionManager = new DvrWatchedPositionManager(this);
25065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
25165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        return mDvrWatchedPositionManager;
25265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
25365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
2541abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
2552e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko    @TargetApi(Build.VERSION_CODES.N)
25665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    public InputSessionManager getInputSessionManager() {
25765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        if (mInputSessionManager == null) {
25865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            mInputSessionManager = new InputSessionManager(this);
2591abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
26065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        return mInputSessionManager;
261816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
262816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
26395961816a768da387f0b5523cf4363ace2044089Nick Chalko    /** Returns {@link ChannelDataManager}. */
2641abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
2657d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko    public ChannelDataManager getChannelDataManager() {
2667d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko        if (mChannelDataManager == null) {
267633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            mChannelDataManager = new ChannelDataManager(this, getTvInputManagerHelper());
2687d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko            mChannelDataManager.start();
2697d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko        }
2707d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko        return mChannelDataManager;
2717d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko    }
2727d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko
273633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    @Override
274633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    public boolean isChannelDataManagerLoadFinished() {
275633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        return mChannelDataManager != null && mChannelDataManager.isDbLoadFinished();
276633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    }
277633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko
27895961816a768da387f0b5523cf4363ace2044089Nick Chalko    /** Returns {@link ProgramDataManager}. */
2791abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
2807d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko    public ProgramDataManager getProgramDataManager() {
281633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        if (mProgramDataManager != null) {
282633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            return mProgramDataManager;
2837d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko        }
28495961816a768da387f0b5523cf4363ace2044089Nick Chalko        Utils.runInMainThreadAndWait(
28595961816a768da387f0b5523cf4363ace2044089Nick Chalko                new Runnable() {
28695961816a768da387f0b5523cf4363ace2044089Nick Chalko                    @Override
28795961816a768da387f0b5523cf4363ace2044089Nick Chalko                    public void run() {
28895961816a768da387f0b5523cf4363ace2044089Nick Chalko                        if (mProgramDataManager == null) {
28995961816a768da387f0b5523cf4363ace2044089Nick Chalko                            mProgramDataManager = new ProgramDataManager(TvApplication.this);
29095961816a768da387f0b5523cf4363ace2044089Nick Chalko                            mProgramDataManager.start();
29195961816a768da387f0b5523cf4363ace2044089Nick Chalko                        }
29295961816a768da387f0b5523cf4363ace2044089Nick Chalko                    }
29395961816a768da387f0b5523cf4363ace2044089Nick Chalko                });
2947d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko        return mProgramDataManager;
2957d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko    }
2967d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko
297633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    @Override
298633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    public boolean isProgramDataManagerCurrentProgramsLoadFinished() {
299633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        return mProgramDataManager != null && mProgramDataManager.isCurrentProgramsLoadFinished();
300633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    }
301633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko
30295961816a768da387f0b5523cf4363ace2044089Nick Chalko    /** Returns {@link PreviewDataManager}. */
303633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    @TargetApi(Build.VERSION_CODES.O)
304633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    @Override
305633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    public PreviewDataManager getPreviewDataManager() {
306633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        if (mPreviewDataManager == null) {
307633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            mPreviewDataManager = new PreviewDataManager(this);
308633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            mPreviewDataManager.start();
309633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        }
310633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        return mPreviewDataManager;
311633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    }
312633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko
31395961816a768da387f0b5523cf4363ace2044089Nick Chalko    /** Returns {@link DvrDataManager}. */
3142e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko    @TargetApi(Build.VERSION_CODES.N)
3151abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
3161abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public DvrDataManager getDvrDataManager() {
3171abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (mDvrDataManager == null) {
318d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            DvrDataManagerImpl dvrDataManager = new DvrDataManagerImpl(this, Clock.SYSTEM);
319d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            mDvrDataManager = dvrDataManager;
320d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            dvrDataManager.start();
3211abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
3221abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return mDvrDataManager;
3231abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
3241abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
32565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
326944779887775bd950cf1abf348d2df461593f6abLive Channels Team    @TargetApi(Build.VERSION_CODES.N)
327944779887775bd950cf1abf348d2df461593f6abLive Channels Team    public RecordingStorageStatusManager getRecordingStorageStatusManager() {
328944779887775bd950cf1abf348d2df461593f6abLive Channels Team        if (mDvrStorageStatusManager == null) {
329944779887775bd950cf1abf348d2df461593f6abLive Channels Team            mDvrStorageStatusManager = new DvrStorageStatusManager(this);
33065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
331944779887775bd950cf1abf348d2df461593f6abLive Channels Team        return mDvrStorageStatusManager;
33265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
33365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
33438fef3bf253578f518d1bc727da4afb263194398Nick Chalko    /** Returns the main activity information. */
33538fef3bf253578f518d1bc727da4afb263194398Nick Chalko    @Override
33638fef3bf253578f518d1bc727da4afb263194398Nick Chalko    public MainActivityWrapper getMainActivityWrapper() {
33738fef3bf253578f518d1bc727da4afb263194398Nick Chalko        return mMainActivityWrapper;
33838fef3bf253578f518d1bc727da4afb263194398Nick Chalko    }
33938fef3bf253578f518d1bc727da4afb263194398Nick Chalko
340944779887775bd950cf1abf348d2df461593f6abLive Channels Team    /** Returns {@link TvInputManagerHelper}. */
34138fef3bf253578f518d1bc727da4afb263194398Nick Chalko    @Override
342944779887775bd950cf1abf348d2df461593f6abLive Channels Team    public TvInputManagerHelper getTvInputManagerHelper() {
343944779887775bd950cf1abf348d2df461593f6abLive Channels Team        if (mTvInputManagerHelper == null) {
344944779887775bd950cf1abf348d2df461593f6abLive Channels Team            mTvInputManagerHelper = new TvInputManagerHelper(this);
345944779887775bd950cf1abf348d2df461593f6abLive Channels Team            mTvInputManagerHelper.start();
34638fef3bf253578f518d1bc727da4afb263194398Nick Chalko        }
347944779887775bd950cf1abf348d2df461593f6abLive Channels Team        return mTvInputManagerHelper;
34838fef3bf253578f518d1bc727da4afb263194398Nick Chalko    }
34938fef3bf253578f518d1bc727da4afb263194398Nick Chalko
35065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
351944779887775bd950cf1abf348d2df461593f6abLive Channels Team    public synchronized TunerInputController getTunerInputController() {
352944779887775bd950cf1abf348d2df461593f6abLive Channels Team        if (mTunerInputController == null) {
353944779887775bd950cf1abf348d2df461593f6abLive Channels Team            mTunerInputController =
354944779887775bd950cf1abf348d2df461593f6abLive Channels Team                    new TunerInputController(
355944779887775bd950cf1abf348d2df461593f6abLive Channels Team                            ComponentName.unflattenFromString(getEmbeddedTunerInputId()));
35665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
357944779887775bd950cf1abf348d2df461593f6abLive Channels Team        return mTunerInputController;
35865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
35965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
360633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    @Override
361633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    public boolean isRunningInMainProcess() {
362633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        return mRunningInMainProcess != null && mRunningInMainProcess;
363633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    }
364633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko
36565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    /**
36695961816a768da387f0b5523cf4363ace2044089Nick Chalko     * SelectInputActivity is set in {@link SelectInputActivity#onCreate} and cleared in {@link
36795961816a768da387f0b5523cf4363ace2044089Nick Chalko     * SelectInputActivity#onDestroy}.
3687d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko     */
3697d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko    public void setSelectInputActivity(SelectInputActivity activity) {
3707d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko        mSelectInputActivity = activity;
371816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
372816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
373633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    public void handleGuideKey() {
374633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        if (!mMainActivityWrapper.isResumed()) {
375633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            startActivity(new Intent(Intent.ACTION_VIEW, TvContract.Programs.CONTENT_URI));
376633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        } else {
377633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            mMainActivityWrapper.getMainActivity().getOverlayManager().toggleProgramGuide();
378633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        }
379633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    }
380633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko
38195961816a768da387f0b5523cf4363ace2044089Nick Chalko    /** Handles the global key KEYCODE_TV. */
382816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void handleTvKey() {
383ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        if (!mMainActivityWrapper.isResumed()) {
384816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            startMainActivity(null);
385816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
386816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
387816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
3887eb2f57e74b3681dfe1c7089dc41963c0f61db7dnchalko    /** Handles the global key KEYCODE_DVR. */
3897eb2f57e74b3681dfe1c7089dc41963c0f61db7dnchalko    public void handleDvrKey() {
3907eb2f57e74b3681dfe1c7089dc41963c0f61db7dnchalko        startActivity(new Intent(this, DvrBrowseActivity.class));
3917eb2f57e74b3681dfe1c7089dc41963c0f61db7dnchalko    }
3927eb2f57e74b3681dfe1c7089dc41963c0f61db7dnchalko
39395961816a768da387f0b5523cf4363ace2044089Nick Chalko    /** Handles the global key KEYCODE_TV_INPUT. */
394816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void handleTvInputKey() {
395816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        TvInputManager tvInputManager = (TvInputManager) getSystemService(Context.TV_INPUT_SERVICE);
396816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        List<TvInputInfo> tvInputs = tvInputManager.getTvInputList();
397816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        int inputCount = 0;
398816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        boolean hasTunerInput = false;
399816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        for (TvInputInfo input : tvInputs) {
400816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            if (input.isPassthroughInput()) {
4012e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                if (!input.isHidden(this)) {
4022e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                    ++inputCount;
4032e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                }
404816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            } else if (!hasTunerInput) {
405816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                hasTunerInput = true;
406816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                ++inputCount;
407816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            }
408816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
409816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (inputCount < 2) {
410816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            return;
411816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
41295961816a768da387f0b5523cf4363ace2044089Nick Chalko        Activity activityToHandle =
41395961816a768da387f0b5523cf4363ace2044089Nick Chalko                mMainActivityWrapper.isResumed()
41495961816a768da387f0b5523cf4363ace2044089Nick Chalko                        ? mMainActivityWrapper.getMainActivity()
41595961816a768da387f0b5523cf4363ace2044089Nick Chalko                        : mSelectInputActivity;
4167d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko        if (activityToHandle != null) {
417816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            // If startActivity is called, MainActivity.onPause is unnecessarily called. To
418816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            // prevent it, MainActivity.dispatchKeyEvent is directly called.
4197d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko            activityToHandle.dispatchKeyEvent(
420816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_TV_INPUT));
42195961816a768da387f0b5523cf4363ace2044089Nick Chalko            activityToHandle.dispatchKeyEvent(
42295961816a768da387f0b5523cf4363ace2044089Nick Chalko                    new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_TV_INPUT));
423ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        } else if (mMainActivityWrapper.isStarted()) {
424816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            Bundle extras = new Bundle();
425816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            extras.putString(Utils.EXTRA_KEY_ACTION, Utils.EXTRA_ACTION_SHOW_TV_INPUT);
426816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            startMainActivity(extras);
4277d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko        } else {
42895961816a768da387f0b5523cf4363ace2044089Nick Chalko            startActivity(
42995961816a768da387f0b5523cf4363ace2044089Nick Chalko                    new Intent(this, SelectInputActivity.class)
43095961816a768da387f0b5523cf4363ace2044089Nick Chalko                            .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
431816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
432816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
433816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
434816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private void startMainActivity(Bundle extras) {
435816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // The use of FLAG_ACTIVITY_NEW_TASK enables arbitrary applications to access the intent
436816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // sent to the root activity. Having said that, we should be fine here since such an intent
437816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // does not carry any important user data.
43895961816a768da387f0b5523cf4363ace2044089Nick Chalko        Intent intent =
43995961816a768da387f0b5523cf4363ace2044089Nick Chalko                new Intent(this, MainActivity.class).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
440816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (extras != null) {
441816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            intent.putExtras(extras);
442816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
443816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        startActivity(intent);
444816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
445816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
446ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    /**
447ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko     * Returns the version name of the live channels.
448ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko     *
449ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko     * @see PackageInfo#versionName
450ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko     */
451ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    public String getVersionName() {
452ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        return mVersionName;
453816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
45407b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko
4551abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    /**
456944779887775bd950cf1abf348d2df461593f6abLive Channels Team     * Checks the input counts and enable/disable TvActivity. Also upda162 the input list in {@link
45795961816a768da387f0b5523cf4363ace2044089Nick Chalko     * SetupUtils}.
4581abddd9f6225298066094e20a6c29061b6af4590Nick Chalko     */
459944779887775bd950cf1abf348d2df461593f6abLive Channels Team    @Override
4601abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public void handleInputCountChanged() {
4612e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko        handleInputCountChanged(false, false, false);
4622e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko    }
4632e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko
4642e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko    /**
46595961816a768da387f0b5523cf4363ace2044089Nick Chalko     * Checks the input counts and enable/disable TvActivity. Also updates the input list in {@link
46695961816a768da387f0b5523cf4363ace2044089Nick Chalko     * SetupUtils}.
4672e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko     *
468944779887775bd950cf1abf348d2df461593f6abLive Channels Team     * @param calledByTunerServiceChanged true if it is called when BaseTunerTvInputService is
469944779887775bd950cf1abf348d2df461593f6abLive Channels Team     *     enabled or disabled.
4702e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko     * @param tunerServiceEnabled it's available only when calledByTunerServiceChanged is true.
47195961816a768da387f0b5523cf4363ace2044089Nick Chalko     * @param dontKillApp when TvActivity is enabled or disabled by this method, the app restarts by
47295961816a768da387f0b5523cf4363ace2044089Nick Chalko     *     default. But, if dontKillApp is true, the app won't restart.
4732e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko     */
47495961816a768da387f0b5523cf4363ace2044089Nick Chalko    public void handleInputCountChanged(
47595961816a768da387f0b5523cf4363ace2044089Nick Chalko            boolean calledByTunerServiceChanged, boolean tunerServiceEnabled, boolean dontKillApp) {
4761abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        TvInputManager inputManager = (TvInputManager) getSystemService(Context.TV_INPUT_SERVICE);
47795961816a768da387f0b5523cf4363ace2044089Nick Chalko        boolean enable =
47895961816a768da387f0b5523cf4363ace2044089Nick Chalko                (calledByTunerServiceChanged && tunerServiceEnabled)
479944779887775bd950cf1abf348d2df461593f6abLive Channels Team                        || TvFeatures.UNHIDE.isEnabled(TvApplication.this);
4802e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko        if (!enable) {
4811abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            List<TvInputInfo> inputs = inputManager.getTvInputList();
4822e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko            boolean skipTunerInputCheck = false;
4831abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            // Enable the TvActivity only if there is at least one tuner type input.
4842e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko            if (!skipTunerInputCheck) {
4852e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                for (TvInputInfo input : inputs) {
48695961816a768da387f0b5523cf4363ace2044089Nick Chalko                    if (calledByTunerServiceChanged
48795961816a768da387f0b5523cf4363ace2044089Nick Chalko                            && !tunerServiceEnabled
488944779887775bd950cf1abf348d2df461593f6abLive Channels Team                            && getEmbeddedTunerInputId().equals(input.getId())) {
4892e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                        continue;
4902e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                    }
4912e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                    if (input.getType() == TvInputInfo.TYPE_TUNER) {
4922e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                        enable = true;
4932e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                        break;
4942e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                    }
4951abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                }
4961abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            }
497ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            if (DEBUG) Log.d(TAG, "Enable MainActivity: " + enable);
498ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        }
499ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        PackageManager packageManager = getPackageManager();
500ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        ComponentName name = new ComponentName(this, TvActivity.class);
50195961816a768da387f0b5523cf4363ace2044089Nick Chalko        int newState =
50295961816a768da387f0b5523cf4363ace2044089Nick Chalko                enable
50395961816a768da387f0b5523cf4363ace2044089Nick Chalko                        ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
50495961816a768da387f0b5523cf4363ace2044089Nick Chalko                        : PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
505ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        if (packageManager.getComponentEnabledSetting(name) != newState) {
50695961816a768da387f0b5523cf4363ace2044089Nick Chalko            packageManager.setComponentEnabledSetting(
50795961816a768da387f0b5523cf4363ace2044089Nick Chalko                    name, newState, dontKillApp ? PackageManager.DONT_KILL_APP : 0);
508633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            Log.i(TAG, (enable ? "Un-hide" : "Hide") + " Live TV.");
5091abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
510944779887775bd950cf1abf348d2df461593f6abLive Channels Team        getSetupUtils().onInputListUpdated(inputManager);
51165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
5120645b17e2818b69b996da48fd93731bc8a01f114Live Channels Team
5130645b17e2818b69b996da48fd93731bc8a01f114Live Channels Team    @Override
5140645b17e2818b69b996da48fd93731bc8a01f114Live Channels Team    public Executor getDbExecutor() {
5150645b17e2818b69b996da48fd93731bc8a01f114Live Channels Team        return DB_EXECUTOR;
5160645b17e2818b69b996da48fd93731bc8a01f114Live Channels Team    }
517816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko}
518