TvApplication.java revision 95961816a768da387f0b5523cf4363ace2044089
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;
21816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.app.Application;
221abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport android.content.ComponentName;
23816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.content.Context;
24816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.content.Intent;
2565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.content.SharedPreferences;
26816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.content.pm.PackageInfo;
27816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.content.pm.PackageManager;
28633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalkoimport android.media.tv.TvContract;
29816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.media.tv.TvInputInfo;
30816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.media.tv.TvInputManager;
311abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport android.media.tv.TvInputManager.TvInputCallback;
32633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalkoimport android.os.AsyncTask;
332e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalkoimport android.os.Build;
34816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.os.Bundle;
3507b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalkoimport android.os.StrictMode;
361abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport android.support.annotation.Nullable;
37633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalkoimport android.support.annotation.VisibleForTesting;
3865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.text.TextUtils;
39816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.util.Log;
40816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.view.KeyEvent;
41816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport com.android.tv.analytics.Analytics;
42816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport com.android.tv.analytics.StubAnalytics;
43816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport com.android.tv.analytics.Tracker;
44ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport com.android.tv.common.BuildConfig;
45ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport com.android.tv.common.SharedPreferencesUtils;
4665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.android.tv.common.SoftPreconditions;
471abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.android.tv.common.TvCommonUtils;
48ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport com.android.tv.common.feature.CommonFeatures;
49ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport com.android.tv.common.ui.setup.animation.SetupAnimationHelper;
5065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.android.tv.config.DefaultConfigManager;
5165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.android.tv.config.RemoteConfig;
527d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport com.android.tv.data.ChannelDataManager;
53633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalkoimport com.android.tv.data.PreviewDataManager;
547d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport com.android.tv.data.ProgramDataManager;
55633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalkoimport com.android.tv.data.epg.EpgFetcher;
561abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.android.tv.dvr.DvrDataManager;
571abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.android.tv.dvr.DvrDataManagerImpl;
581abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.android.tv.dvr.DvrManager;
5965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.android.tv.dvr.DvrScheduleManager;
60d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport com.android.tv.dvr.DvrStorageStatusManager;
6165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.android.tv.dvr.DvrWatchedPositionManager;
62633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalkoimport com.android.tv.dvr.recorder.RecordingScheduler;
63633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalkoimport com.android.tv.perf.EventNames;
64633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalkoimport com.android.tv.perf.PerformanceMonitor;
65633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalkoimport com.android.tv.perf.StubPerformanceMonitor;
66633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalkoimport com.android.tv.perf.TimerEvent;
67633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalkoimport com.android.tv.recommendation.ChannelPreviewUpdater;
68633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalkoimport com.android.tv.recommendation.RecordedProgramPreviewUpdater;
69633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalkoimport com.android.tv.tuner.TunerInputController;
7065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.android.tv.tuner.TunerPreferences;
7165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.android.tv.tuner.tvinput.TunerTvInputService;
7265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.android.tv.tuner.util.TunerInputInfoUtils;
7365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.android.tv.util.AccountHelper;
742e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalkoimport com.android.tv.util.Clock;
75633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalkoimport com.android.tv.util.Debug;
76633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalkoimport com.android.tv.util.PermissionUtils;
771abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.android.tv.util.SetupUtils;
7807b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalkoimport com.android.tv.util.SystemProperties;
7907b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalkoimport com.android.tv.util.TvInputManagerHelper;
80816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport com.android.tv.util.Utils;
81816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport java.util.List;
82816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
831abddd9f6225298066094e20a6c29061b6af4590Nick Chalkopublic class TvApplication extends Application implements ApplicationSingletons {
84816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private static final String TAG = "TvApplication";
85816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private static final boolean DEBUG = false;
86633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    private static final TimerEvent sAppStartTimer = StubPerformanceMonitor.startBootstrapTimer();
87633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko
88633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    /**
89633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko     * An instance of {@link ApplicationSingletons}. Note that this can be set directly only for the
90633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko     * test purpose.
91633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko     */
9295961816a768da387f0b5523cf4363ace2044089Nick Chalko    @VisibleForTesting public static ApplicationSingletons sAppSingletons;
93816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
941abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    /**
9595961816a768da387f0b5523cf4363ace2044089Nick Chalko     * Broadcast Action: The user has updated LC to a new version that supports tuner input. {@link
9695961816a768da387f0b5523cf4363ace2044089Nick Chalko     * com.android.tv.tuner.TunerInputController} will recevice this intent to check the existence
9795961816a768da387f0b5523cf4363ace2044089Nick Chalko     * of tuner input when the new version is first launched.
981abddd9f6225298066094e20a6c29061b6af4590Nick Chalko     */
9965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    public static final String ACTION_APPLICATION_FIRST_LAUNCHED =
10065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            "com.android.tv.action.APPLICATION_FIRST_LAUNCHED";
10195961816a768da387f0b5523cf4363ace2044089Nick Chalko
10265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private static final String PREFERENCE_IS_FIRST_LAUNCH = "is_first_launch";
10365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
104633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    private RemoteConfig mRemoteConfig;
105ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    private String mVersionName = "";
106ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko
107ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    private final MainActivityWrapper mMainActivityWrapper = new MainActivityWrapper();
1081abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1097d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko    private SelectInputActivity mSelectInputActivity;
1107d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko    private Analytics mAnalytics;
111816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private Tracker mTracker;
11207b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko    private TvInputManagerHelper mTvInputManagerHelper;
1137d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko    private ChannelDataManager mChannelDataManager;
114633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    private volatile ProgramDataManager mProgramDataManager;
115633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    private PreviewDataManager mPreviewDataManager;
1161abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private DvrManager mDvrManager;
11765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private DvrScheduleManager mDvrScheduleManager;
118ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    private DvrDataManager mDvrDataManager;
119d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    private DvrStorageStatusManager mDvrStorageStatusManager;
12065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private DvrWatchedPositionManager mDvrWatchedPositionManager;
121633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    private RecordingScheduler mRecordingScheduler;
12295961816a768da387f0b5523cf4363ace2044089Nick Chalko    @Nullable private InputSessionManager mInputSessionManager;
12365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private AccountHelper mAccountHelper;
12465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    // When this variable is null, we don't know in which process TvApplication runs.
12565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private Boolean mRunningInMainProcess;
126633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    private PerformanceMonitor mPerformanceMonitor;
127816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
128816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    @Override
129816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void onCreate() {
130816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        super.onCreate();
131633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        if (!PermissionUtils.hasInternet(this)) {
132633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            // When an isolated process starts, just skip all the initialization.
133633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            return;
134633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        }
135633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        Debug.getTimer(Debug.TAG_START_UP_TIMER).start();
136633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        Debug.getTimer(Debug.TAG_START_UP_TIMER).log("Start TvApplication.onCreate");
13795961816a768da387f0b5523cf4363ace2044089Nick Chalko        SharedPreferencesUtils.initialize(
13895961816a768da387f0b5523cf4363ace2044089Nick Chalko                this,
13995961816a768da387f0b5523cf4363ace2044089Nick Chalko                new Runnable() {
14095961816a768da387f0b5523cf4363ace2044089Nick Chalko                    @Override
14195961816a768da387f0b5523cf4363ace2044089Nick Chalko                    public void run() {
14295961816a768da387f0b5523cf4363ace2044089Nick Chalko                        if (mRunningInMainProcess != null && mRunningInMainProcess) {
14395961816a768da387f0b5523cf4363ace2044089Nick Chalko                            checkTunerServiceOnFirstLaunch();
14495961816a768da387f0b5523cf4363ace2044089Nick Chalko                        }
14595961816a768da387f0b5523cf4363ace2044089Nick Chalko                    }
14695961816a768da387f0b5523cf4363ace2044089Nick Chalko                });
14765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        // TunerPreferences is used to enable/disable the tuner input even when TUNER feature is
14865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        // disabled.
14965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        TunerPreferences.initialize(this);
1501abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        try {
1511abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            PackageInfo pInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
152ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            mVersionName = pInfo.versionName;
1531abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        } catch (PackageManager.NameNotFoundException e) {
154ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            Log.w(TAG, "Unable to find package '" + getPackageName() + "'.", e);
155ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            mVersionName = "";
1561abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
1571abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        Log.i(TAG, "Starting Live TV " + getVersionName());
15865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
15907b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko        // Only set StrictMode for ENG builds because the build server only produces userdebug
16007b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko        // builds.
16107b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko        if (BuildConfig.ENG && SystemProperties.ALLOW_STRICT_MODE.getValue()) {
162d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            StrictMode.ThreadPolicy.Builder threadPolicyBuilder =
163d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                    new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog();
164d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            StrictMode.VmPolicy.Builder vmPolicyBuilder =
165633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko                    new StrictMode.VmPolicy.Builder().detectAll().penaltyDeath();
166d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            if (!TvCommonUtils.isRunningInTest()) {
167d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                threadPolicyBuilder.penaltyDialog();
16807b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko            }
169d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            StrictMode.setThreadPolicy(threadPolicyBuilder.build());
17007b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko            StrictMode.setVmPolicy(vmPolicyBuilder.build());
17107b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko        }
17207b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko        if (BuildConfig.ENG && !SystemProperties.ALLOW_ANALYTICS_IN_ENG.getValue()) {
1737d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko            mAnalytics = StubAnalytics.getInstance(this);
17407b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko        } else {
1757d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko            mAnalytics = StubAnalytics.getInstance(this);
1767d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko        }
1777d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko        mTracker = mAnalytics.getDefaultTracker();
178633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        getTvInputManagerHelper();
179ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        // In SetupFragment, transitions are set in the constructor. Because the fragment can be
180ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        // created in Activity.onCreate() by the framework, SetupAnimationHelper should be
181ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        // initialized here before Activity.onCreate() is called.
182ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        SetupAnimationHelper.initialize(this);
183633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko
18465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        Log.i(TAG, "Started Live TV " + mVersionName);
185633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        Debug.getTimer(Debug.TAG_START_UP_TIMER).log("finish TvApplication.onCreate");
186633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        getPerformanceMonitor().stopTimer(sAppStartTimer, EventNames.APPLICATION_ONCREATE);
18765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
18865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
18965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private void setCurrentRunningProcess(boolean isMainProcess) {
19065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        if (mRunningInMainProcess != null) {
19165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            SoftPreconditions.checkState(isMainProcess == mRunningInMainProcess);
19265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            return;
19365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
19495961816a768da387f0b5523cf4363ace2044089Nick Chalko        Debug.getTimer(Debug.TAG_START_UP_TIMER)
19595961816a768da387f0b5523cf4363ace2044089Nick Chalko                .log("start TvApplication.setCurrentRunningProcess");
19665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mRunningInMainProcess = isMainProcess;
197d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        if (CommonFeatures.DVR.isEnabled(this)) {
198d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            mDvrStorageStatusManager = new DvrStorageStatusManager(this, mRunningInMainProcess);
199d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        }
200633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        new AsyncTask<Void, Void, Void>() {
201633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            @Override
202633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            protected Void doInBackground(Void... params) {
203633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko                // Fetch remote config
204633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko                getRemoteConfig().fetch(null);
205633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko                return null;
206633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            }
207633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        }.execute();
20865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        if (mRunningInMainProcess) {
20995961816a768da387f0b5523cf4363ace2044089Nick Chalko            getTvInputManagerHelper()
21095961816a768da387f0b5523cf4363ace2044089Nick Chalko                    .addCallback(
21195961816a768da387f0b5523cf4363ace2044089Nick Chalko                            new TvInputCallback() {
21295961816a768da387f0b5523cf4363ace2044089Nick Chalko                                @Override
21395961816a768da387f0b5523cf4363ace2044089Nick Chalko                                public void onInputAdded(String inputId) {
21495961816a768da387f0b5523cf4363ace2044089Nick Chalko                                    if (Features.TUNER.isEnabled(TvApplication.this)
21595961816a768da387f0b5523cf4363ace2044089Nick Chalko                                            && TextUtils.equals(
21695961816a768da387f0b5523cf4363ace2044089Nick Chalko                                                    inputId,
21795961816a768da387f0b5523cf4363ace2044089Nick Chalko                                                    TunerTvInputService.getInputId(
21895961816a768da387f0b5523cf4363ace2044089Nick Chalko                                                            TvApplication.this))) {
21995961816a768da387f0b5523cf4363ace2044089Nick Chalko                                        TunerInputInfoUtils.updateTunerInputInfo(
22095961816a768da387f0b5523cf4363ace2044089Nick Chalko                                                TvApplication.this);
22195961816a768da387f0b5523cf4363ace2044089Nick Chalko                                    }
22295961816a768da387f0b5523cf4363ace2044089Nick Chalko                                    handleInputCountChanged();
22395961816a768da387f0b5523cf4363ace2044089Nick Chalko                                }
22495961816a768da387f0b5523cf4363ace2044089Nick Chalko
22595961816a768da387f0b5523cf4363ace2044089Nick Chalko                                @Override
22695961816a768da387f0b5523cf4363ace2044089Nick Chalko                                public void onInputRemoved(String inputId) {
22795961816a768da387f0b5523cf4363ace2044089Nick Chalko                                    handleInputCountChanged();
22895961816a768da387f0b5523cf4363ace2044089Nick Chalko                                }
22995961816a768da387f0b5523cf4363ace2044089Nick Chalko                            });
23065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            if (Features.TUNER.isEnabled(this)) {
23165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                // If the tuner input service is added before the app is started, we need to
23265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                // handle it here.
233633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko                TunerInputInfoUtils.updateTunerInputInfo(TvApplication.this);
23465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
23565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            if (CommonFeatures.DVR.isEnabled(this)) {
23665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                mDvrScheduleManager = new DvrScheduleManager(this);
23765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                mDvrManager = new DvrManager(this);
238633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko                mRecordingScheduler = RecordingScheduler.createScheduler(this);
239633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            }
240633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            EpgFetcher.getInstance(this).startRoutineService();
241633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
242633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko                ChannelPreviewUpdater.getInstance(this).startRoutineService();
243633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko                RecordedProgramPreviewUpdater.getInstance(this)
244633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko                        .updatePreviewDataForRecordedPrograms();
24565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
24665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
24795961816a768da387f0b5523cf4363ace2044089Nick Chalko        Debug.getTimer(Debug.TAG_START_UP_TIMER)
24895961816a768da387f0b5523cf4363ace2044089Nick Chalko                .log("finish TvApplication.setCurrentRunningProcess");
24965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
25065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
25165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private void checkTunerServiceOnFirstLaunch() {
25295961816a768da387f0b5523cf4363ace2044089Nick Chalko        SharedPreferences sharedPreferences =
25395961816a768da387f0b5523cf4363ace2044089Nick Chalko                this.getSharedPreferences(
25495961816a768da387f0b5523cf4363ace2044089Nick Chalko                        SharedPreferencesUtils.SHARED_PREF_FEATURES, Context.MODE_PRIVATE);
25565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        boolean isFirstLaunch = sharedPreferences.getBoolean(PREFERENCE_IS_FIRST_LAUNCH, true);
25665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        if (isFirstLaunch) {
25765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            if (DEBUG) Log.d(TAG, "Congratulations, it's the first launch!");
258633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            TunerInputController.onCheckingUsbTunerStatus(this, ACTION_APPLICATION_FIRST_LAUNCHED);
25965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            SharedPreferences.Editor editor = sharedPreferences.edit();
26065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            editor.putBoolean(PREFERENCE_IS_FIRST_LAUNCH, false);
26165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            editor.apply();
26265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
2631abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2641abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
26595961816a768da387f0b5523cf4363ace2044089Nick Chalko    /** Returns the {@link DvrManager}. */
2661abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
2671abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public DvrManager getDvrManager() {
2681abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return mDvrManager;
2691abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2701abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
27195961816a768da387f0b5523cf4363ace2044089Nick Chalko    /** Returns the {@link DvrScheduleManager}. */
27265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
27365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    public DvrScheduleManager getDvrScheduleManager() {
27465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        return mDvrScheduleManager;
27565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
27665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
27795961816a768da387f0b5523cf4363ace2044089Nick Chalko    /** Returns the {@link RecordingScheduler}. */
278633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    @Override
279633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    @Nullable
280633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    public RecordingScheduler getRecordingScheduler() {
281633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        return mRecordingScheduler;
282633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    }
283633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko
28495961816a768da387f0b5523cf4363ace2044089Nick Chalko    /** Returns the {@link DvrWatchedPositionManager}. */
28565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
28665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    public DvrWatchedPositionManager getDvrWatchedPositionManager() {
28765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        if (mDvrWatchedPositionManager == null) {
28865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            mDvrWatchedPositionManager = new DvrWatchedPositionManager(this);
28965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
29065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        return mDvrWatchedPositionManager;
29165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
29265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
2931abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
2942e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko    @TargetApi(Build.VERSION_CODES.N)
29565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    public InputSessionManager getInputSessionManager() {
29665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        if (mInputSessionManager == null) {
29765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            mInputSessionManager = new InputSessionManager(this);
2981abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
29965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        return mInputSessionManager;
300816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
301816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
30295961816a768da387f0b5523cf4363ace2044089Nick Chalko    /** Returns the {@link Analytics}. */
3031abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
3047d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko    public Analytics getAnalytics() {
3057d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko        return mAnalytics;
3067d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko    }
3077d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko
30895961816a768da387f0b5523cf4363ace2044089Nick Chalko    /** Returns the default tracker. */
3091abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
310816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public Tracker getTracker() {
311816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        return mTracker;
312816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
313816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
31495961816a768da387f0b5523cf4363ace2044089Nick Chalko    /** Returns {@link ChannelDataManager}. */
3151abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
3167d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko    public ChannelDataManager getChannelDataManager() {
3177d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko        if (mChannelDataManager == null) {
318633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            mChannelDataManager = new ChannelDataManager(this, getTvInputManagerHelper());
3197d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko            mChannelDataManager.start();
3207d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko        }
3217d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko        return mChannelDataManager;
3227d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko    }
3237d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko
324633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    @Override
325633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    public boolean isChannelDataManagerLoadFinished() {
326633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        return mChannelDataManager != null && mChannelDataManager.isDbLoadFinished();
327633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    }
328633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko
32995961816a768da387f0b5523cf4363ace2044089Nick Chalko    /** Returns {@link ProgramDataManager}. */
3301abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
3317d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko    public ProgramDataManager getProgramDataManager() {
332633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        if (mProgramDataManager != null) {
333633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            return mProgramDataManager;
3347d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko        }
33595961816a768da387f0b5523cf4363ace2044089Nick Chalko        Utils.runInMainThreadAndWait(
33695961816a768da387f0b5523cf4363ace2044089Nick Chalko                new Runnable() {
33795961816a768da387f0b5523cf4363ace2044089Nick Chalko                    @Override
33895961816a768da387f0b5523cf4363ace2044089Nick Chalko                    public void run() {
33995961816a768da387f0b5523cf4363ace2044089Nick Chalko                        if (mProgramDataManager == null) {
34095961816a768da387f0b5523cf4363ace2044089Nick Chalko                            mProgramDataManager = new ProgramDataManager(TvApplication.this);
34195961816a768da387f0b5523cf4363ace2044089Nick Chalko                            mProgramDataManager.start();
34295961816a768da387f0b5523cf4363ace2044089Nick Chalko                        }
34395961816a768da387f0b5523cf4363ace2044089Nick Chalko                    }
34495961816a768da387f0b5523cf4363ace2044089Nick Chalko                });
3457d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko        return mProgramDataManager;
3467d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko    }
3477d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko
348633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    @Override
349633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    public boolean isProgramDataManagerCurrentProgramsLoadFinished() {
350633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        return mProgramDataManager != null && mProgramDataManager.isCurrentProgramsLoadFinished();
351633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    }
352633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko
35395961816a768da387f0b5523cf4363ace2044089Nick Chalko    /** Returns {@link PreviewDataManager}. */
354633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    @TargetApi(Build.VERSION_CODES.O)
355633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    @Override
356633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    public PreviewDataManager getPreviewDataManager() {
357633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        if (mPreviewDataManager == null) {
358633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            mPreviewDataManager = new PreviewDataManager(this);
359633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            mPreviewDataManager.start();
360633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        }
361633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        return mPreviewDataManager;
362633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    }
363633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko
36495961816a768da387f0b5523cf4363ace2044089Nick Chalko    /** Returns {@link DvrDataManager}. */
3652e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko    @TargetApi(Build.VERSION_CODES.N)
3661abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
3671abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public DvrDataManager getDvrDataManager() {
3681abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (mDvrDataManager == null) {
369d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            DvrDataManagerImpl dvrDataManager = new DvrDataManagerImpl(this, Clock.SYSTEM);
370d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            mDvrDataManager = dvrDataManager;
371d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            dvrDataManager.start();
3721abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
3731abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return mDvrDataManager;
3741abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
3751abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
37695961816a768da387f0b5523cf4363ace2044089Nick Chalko    /** Returns {@link DvrStorageStatusManager}. */
377d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    @TargetApi(Build.VERSION_CODES.N)
378d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    @Override
379d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    public DvrStorageStatusManager getDvrStorageStatusManager() {
380d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        return mDvrStorageStatusManager;
381d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    }
382d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko
38395961816a768da387f0b5523cf4363ace2044089Nick Chalko    /** Returns {@link TvInputManagerHelper}. */
3841abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
38507b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko    public TvInputManagerHelper getTvInputManagerHelper() {
386633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        if (mTvInputManagerHelper == null) {
387633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            mTvInputManagerHelper = new TvInputManagerHelper(this);
388633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            mTvInputManagerHelper.start();
389633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        }
39007b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko        return mTvInputManagerHelper;
39107b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko    }
39207b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko
39395961816a768da387f0b5523cf4363ace2044089Nick Chalko    /** Returns the main activity information. */
394ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    @Override
395ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    public MainActivityWrapper getMainActivityWrapper() {
396ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        return mMainActivityWrapper;
3977d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko    }
3987d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko
39995961816a768da387f0b5523cf4363ace2044089Nick Chalko    /** Returns the {@link AccountHelper}. */
40065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
40165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    public AccountHelper getAccountHelper() {
40265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        if (mAccountHelper == null) {
40365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            mAccountHelper = new AccountHelper(getApplicationContext());
40465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
40565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        return mAccountHelper;
40665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
40765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
40865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
40965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    public RemoteConfig getRemoteConfig() {
41065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        if (mRemoteConfig == null) {
41165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            // No need to synchronize this, it does not hurt to create two and throw one away.
41265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            mRemoteConfig = DefaultConfigManager.createInstance(this).getRemoteConfig();
41365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
41465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        return mRemoteConfig;
41565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
41665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
417633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    @Override
418633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    public boolean isRunningInMainProcess() {
419633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        return mRunningInMainProcess != null && mRunningInMainProcess;
420633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    }
421633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko
422633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    @Override
423633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    public PerformanceMonitor getPerformanceMonitor() {
424633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        if (mPerformanceMonitor == null) {
425633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            mPerformanceMonitor = StubPerformanceMonitor.initialize(this);
426633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        }
427633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        return mPerformanceMonitor;
428633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    }
429633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko
43065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    /**
43195961816a768da387f0b5523cf4363ace2044089Nick Chalko     * SelectInputActivity is set in {@link SelectInputActivity#onCreate} and cleared in {@link
43295961816a768da387f0b5523cf4363ace2044089Nick Chalko     * SelectInputActivity#onDestroy}.
4337d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko     */
4347d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko    public void setSelectInputActivity(SelectInputActivity activity) {
4357d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko        mSelectInputActivity = activity;
436816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
437816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
438633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    public void handleGuideKey() {
439633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        if (!mMainActivityWrapper.isResumed()) {
440633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            startActivity(new Intent(Intent.ACTION_VIEW, TvContract.Programs.CONTENT_URI));
441633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        } else {
442633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            mMainActivityWrapper.getMainActivity().getOverlayManager().toggleProgramGuide();
443633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        }
444633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko    }
445633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko
44695961816a768da387f0b5523cf4363ace2044089Nick Chalko    /** Handles the global key KEYCODE_TV. */
447816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void handleTvKey() {
448ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        if (!mMainActivityWrapper.isResumed()) {
449816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            startMainActivity(null);
450816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
451816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
452816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
45395961816a768da387f0b5523cf4363ace2044089Nick Chalko    /** Handles the global key KEYCODE_TV_INPUT. */
454816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void handleTvInputKey() {
455816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        TvInputManager tvInputManager = (TvInputManager) getSystemService(Context.TV_INPUT_SERVICE);
456816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        List<TvInputInfo> tvInputs = tvInputManager.getTvInputList();
457816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        int inputCount = 0;
458816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        boolean hasTunerInput = false;
459816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        for (TvInputInfo input : tvInputs) {
460816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            if (input.isPassthroughInput()) {
4612e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                if (!input.isHidden(this)) {
4622e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                    ++inputCount;
4632e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                }
464816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            } else if (!hasTunerInput) {
465816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                hasTunerInput = true;
466816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                ++inputCount;
467816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            }
468816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
469816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (inputCount < 2) {
470816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            return;
471816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
47295961816a768da387f0b5523cf4363ace2044089Nick Chalko        Activity activityToHandle =
47395961816a768da387f0b5523cf4363ace2044089Nick Chalko                mMainActivityWrapper.isResumed()
47495961816a768da387f0b5523cf4363ace2044089Nick Chalko                        ? mMainActivityWrapper.getMainActivity()
47595961816a768da387f0b5523cf4363ace2044089Nick Chalko                        : mSelectInputActivity;
4767d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko        if (activityToHandle != null) {
477816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            // If startActivity is called, MainActivity.onPause is unnecessarily called. To
478816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            // prevent it, MainActivity.dispatchKeyEvent is directly called.
4797d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko            activityToHandle.dispatchKeyEvent(
480816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_TV_INPUT));
48195961816a768da387f0b5523cf4363ace2044089Nick Chalko            activityToHandle.dispatchKeyEvent(
48295961816a768da387f0b5523cf4363ace2044089Nick Chalko                    new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_TV_INPUT));
483ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        } else if (mMainActivityWrapper.isStarted()) {
484816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            Bundle extras = new Bundle();
485816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            extras.putString(Utils.EXTRA_KEY_ACTION, Utils.EXTRA_ACTION_SHOW_TV_INPUT);
486816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            startMainActivity(extras);
4877d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko        } else {
48895961816a768da387f0b5523cf4363ace2044089Nick Chalko            startActivity(
48995961816a768da387f0b5523cf4363ace2044089Nick Chalko                    new Intent(this, SelectInputActivity.class)
49095961816a768da387f0b5523cf4363ace2044089Nick Chalko                            .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
491816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
492816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
493816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
494816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private void startMainActivity(Bundle extras) {
495816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // The use of FLAG_ACTIVITY_NEW_TASK enables arbitrary applications to access the intent
496816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // sent to the root activity. Having said that, we should be fine here since such an intent
497816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // does not carry any important user data.
49895961816a768da387f0b5523cf4363ace2044089Nick Chalko        Intent intent =
49995961816a768da387f0b5523cf4363ace2044089Nick Chalko                new Intent(this, MainActivity.class).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
500816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (extras != null) {
501816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            intent.putExtras(extras);
502816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
503816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        startActivity(intent);
504816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
505816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
506ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    /**
507ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko     * Returns the version name of the live channels.
508ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko     *
509ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko     * @see PackageInfo#versionName
510ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko     */
511ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    public String getVersionName() {
512ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        return mVersionName;
513816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
51407b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko
5151abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    /**
51695961816a768da387f0b5523cf4363ace2044089Nick Chalko     * Checks the input counts and enable/disable TvActivity. Also updates the input list in {@link
51795961816a768da387f0b5523cf4363ace2044089Nick Chalko     * SetupUtils}.
5181abddd9f6225298066094e20a6c29061b6af4590Nick Chalko     */
5191abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public void handleInputCountChanged() {
5202e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko        handleInputCountChanged(false, false, false);
5212e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko    }
5222e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko
5232e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko    /**
52495961816a768da387f0b5523cf4363ace2044089Nick Chalko     * Checks the input counts and enable/disable TvActivity. Also updates the input list in {@link
52595961816a768da387f0b5523cf4363ace2044089Nick Chalko     * SetupUtils}.
5262e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko     *
52795961816a768da387f0b5523cf4363ace2044089Nick Chalko     * @param calledByTunerServiceChanged true if it is called when TunerTvInputService is enabled
52895961816a768da387f0b5523cf4363ace2044089Nick Chalko     *     or disabled.
5292e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko     * @param tunerServiceEnabled it's available only when calledByTunerServiceChanged is true.
53095961816a768da387f0b5523cf4363ace2044089Nick Chalko     * @param dontKillApp when TvActivity is enabled or disabled by this method, the app restarts by
53195961816a768da387f0b5523cf4363ace2044089Nick Chalko     *     default. But, if dontKillApp is true, the app won't restart.
5322e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko     */
53395961816a768da387f0b5523cf4363ace2044089Nick Chalko    public void handleInputCountChanged(
53495961816a768da387f0b5523cf4363ace2044089Nick Chalko            boolean calledByTunerServiceChanged, boolean tunerServiceEnabled, boolean dontKillApp) {
5351abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        TvInputManager inputManager = (TvInputManager) getSystemService(Context.TV_INPUT_SERVICE);
53695961816a768da387f0b5523cf4363ace2044089Nick Chalko        boolean enable =
53795961816a768da387f0b5523cf4363ace2044089Nick Chalko                (calledByTunerServiceChanged && tunerServiceEnabled)
53895961816a768da387f0b5523cf4363ace2044089Nick Chalko                        || Features.UNHIDE.isEnabled(TvApplication.this);
5392e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko        if (!enable) {
5401abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            List<TvInputInfo> inputs = inputManager.getTvInputList();
5412e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko            boolean skipTunerInputCheck = false;
5421abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            // Enable the TvActivity only if there is at least one tuner type input.
5432e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko            if (!skipTunerInputCheck) {
5442e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                for (TvInputInfo input : inputs) {
54595961816a768da387f0b5523cf4363ace2044089Nick Chalko                    if (calledByTunerServiceChanged
54695961816a768da387f0b5523cf4363ace2044089Nick Chalko                            && !tunerServiceEnabled
54765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                            && TunerTvInputService.getInputId(this).equals(input.getId())) {
5482e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                        continue;
5492e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                    }
5502e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                    if (input.getType() == TvInputInfo.TYPE_TUNER) {
5512e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                        enable = true;
5522e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                        break;
5532e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                    }
5541abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                }
5551abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            }
556ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            if (DEBUG) Log.d(TAG, "Enable MainActivity: " + enable);
557ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        }
558ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        PackageManager packageManager = getPackageManager();
559ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        ComponentName name = new ComponentName(this, TvActivity.class);
56095961816a768da387f0b5523cf4363ace2044089Nick Chalko        int newState =
56195961816a768da387f0b5523cf4363ace2044089Nick Chalko                enable
56295961816a768da387f0b5523cf4363ace2044089Nick Chalko                        ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
56395961816a768da387f0b5523cf4363ace2044089Nick Chalko                        : PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
564ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        if (packageManager.getComponentEnabledSetting(name) != newState) {
56595961816a768da387f0b5523cf4363ace2044089Nick Chalko            packageManager.setComponentEnabledSetting(
56695961816a768da387f0b5523cf4363ace2044089Nick Chalko                    name, newState, dontKillApp ? PackageManager.DONT_KILL_APP : 0);
567633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            Log.i(TAG, (enable ? "Un-hide" : "Hide") + " Live TV.");
5681abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
5691abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        SetupUtils.getInstance(TvApplication.this).onInputListUpdated(inputManager);
5701abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
57165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
57295961816a768da387f0b5523cf4363ace2044089Nick Chalko    /** Returns the @{@link ApplicationSingletons} using the application context. */
57365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    public static ApplicationSingletons getSingletons(Context context) {
574633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        // No need to be "synchronized" because this doesn't create any instance.
575633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        if (sAppSingletons == null) {
576633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko            sAppSingletons = (ApplicationSingletons) context.getApplicationContext();
577633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        }
578633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        return sAppSingletons;
57965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
58065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
58165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    /**
58295961816a768da387f0b5523cf4363ace2044089Nick Chalko     * Sets true, if TvApplication is running on the main process. If TvApplication runs on tuner
58395961816a768da387f0b5523cf4363ace2044089Nick Chalko     * process or other process, it sets false.
58465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko     *
58595961816a768da387f0b5523cf4363ace2044089Nick Chalko     * <p>Note: it should be called at the beginning of Service.onCreate Activity.onCreate, or
58695961816a768da387f0b5523cf4363ace2044089Nick Chalko     * BroadcastReceiver.onCreate. When it is firstly called after launch, it runs process specific
58795961816a768da387f0b5523cf4363ace2044089Nick Chalko     * initializations.
58865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko     */
58965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    public static void setCurrentRunningProcess(Context context, boolean isMainProcess) {
590633eb826b8c97731dfc5ef12c7bf78a63734275dNick Chalko        // TODO(b/63064354) TvApplication should not have to know if it is "the main process"
59165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        if (context.getApplicationContext() instanceof TvApplication) {
59265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            TvApplication tvApplication = (TvApplication) context.getApplicationContext();
59365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            tvApplication.setCurrentRunningProcess(isMainProcess);
59465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        } else {
59565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            // Application context can be MockTvApplication.
59665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            Log.w(TAG, "It is not a context of TvApplication");
59765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
59865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
599816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko}
600