17d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko/* 27d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * Copyright (C) 2015 The Android Open Source Project 37d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * 47d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * Licensed under the Apache License, Version 2.0 (the "License"); 57d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * you may not use this file except in compliance with the License. 67d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * You may obtain a copy of the License at 77d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * 87d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * http://www.apache.org/licenses/LICENSE-2.0 97d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * 107d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * Unless required by applicable law or agreed to in writing, software 117d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * distributed under the License is distributed on an "AS IS" BASIS, 127d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * See the License for the specific language governing permissions and 147d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * limitations under the License. 157d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko */ 167d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 177d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkopackage com.android.tv; 187d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 197d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport android.app.Activity; 207d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport android.content.ActivityNotFoundException; 216ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport android.content.Context; 227d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport android.content.Intent; 237d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport android.media.tv.TvInputInfo; 247d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport android.os.Bundle; 256ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport android.os.Handler; 266ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport android.os.Looper; 276ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport android.support.annotation.MainThread; 287d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport android.util.Log; 297d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 302e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalkoimport com.android.tv.common.SoftPreconditions; 317d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport com.android.tv.common.TvCommonConstants; 326ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport com.android.tv.data.ChannelDataManager; 336ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport com.android.tv.data.ChannelDataManager.Listener; 3465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.android.tv.data.epg.EpgFetcher; 3565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.android.tv.experiments.Experiments; 367d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport com.android.tv.util.SetupUtils; 377d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport com.android.tv.util.TvInputManagerHelper; 3865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.android.tv.util.Utils; 397d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 406ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport java.util.concurrent.TimeUnit; 416ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 427d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko/** 437d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * An activity to launch a TV input setup activity. 447d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * 457d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * <p> After setup activity is finished, all channels will be browsable. 467d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko */ 477d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkopublic class SetupPassthroughActivity extends Activity { 481abddd9f6225298066094e20a6c29061b6af4590Nick Chalko private static final String TAG = "SetupPassthroughAct"; 497d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko private static final boolean DEBUG = false; 507d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 517d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko private static final int REQUEST_START_SETUP_ACTIVITY = 200; 527d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 536ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko private static ScanTimeoutMonitor sScanTimeoutMonitor; 546ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 557d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko private TvInputInfo mTvInputInfo; 567d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko private Intent mActivityAfterCompletion; 576ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko private boolean mEpgFetcherDuringScan; 587d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 597d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko @Override 607d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko public void onCreate(Bundle savedInstanceState) { 616ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (DEBUG) Log.d(TAG, "onCreate"); 627d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko super.onCreate(savedInstanceState); 631abddd9f6225298066094e20a6c29061b6af4590Nick Chalko ApplicationSingletons appSingletons = TvApplication.getSingletons(this); 641abddd9f6225298066094e20a6c29061b6af4590Nick Chalko TvInputManagerHelper inputManager = appSingletons.getTvInputManagerHelper(); 656ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko Intent intent = getIntent(); 661abddd9f6225298066094e20a6c29061b6af4590Nick Chalko String inputId = intent.getStringExtra(TvCommonConstants.EXTRA_INPUT_ID); 677d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko mTvInputInfo = inputManager.getTvInputInfo(inputId); 681abddd9f6225298066094e20a6c29061b6af4590Nick Chalko mActivityAfterCompletion = intent.getParcelableExtra( 697d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko TvCommonConstants.EXTRA_ACTIVITY_AFTER_COMPLETION); 706ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko boolean needToFetchEpg = Utils.isInternalTvInput(this, mTvInputInfo.getId()) 716ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko && Experiments.CLOUD_EPG.get(); 726ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (needToFetchEpg) { 736ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko // In case when the activity is restored, this flag should be restored as well. 746ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mEpgFetcherDuringScan = true; 7565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 766ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (savedInstanceState == null) { 776ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko SoftPreconditions.checkState( 786ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko intent.getAction().equals(TvCommonConstants.INTENT_ACTION_INPUT_SETUP)); 796ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (DEBUG) Log.d(TAG, "TvInputId " + inputId + " / TvInputInfo " + mTvInputInfo); 806ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (mTvInputInfo == null) { 816ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko Log.w(TAG, "There is no input with the ID " + inputId + "."); 826ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko finish(); 836ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return; 846ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 856ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko Intent setupIntent = 866ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko intent.getExtras().getParcelable(TvCommonConstants.EXTRA_SETUP_INTENT); 876ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (DEBUG) Log.d(TAG, "Setup activity launch intent: " + setupIntent); 886ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (setupIntent == null) { 896ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko Log.w(TAG, "The input (" + mTvInputInfo.getId() + ") doesn't have setup."); 906ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko finish(); 916ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return; 926ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 936ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko SetupUtils.grantEpgPermission(this, mTvInputInfo.getServiceInfo().packageName); 946ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (DEBUG) Log.d(TAG, "Activity after completion " + mActivityAfterCompletion); 956ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko // If EXTRA_SETUP_INTENT is not removed, an infinite recursion happens during 966ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko // setupIntent.putExtras(intent.getExtras()). 976ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko Bundle extras = intent.getExtras(); 986ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko extras.remove(TvCommonConstants.EXTRA_SETUP_INTENT); 996ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko setupIntent.putExtras(extras); 1006ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko try { 1016ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko startActivityForResult(setupIntent, REQUEST_START_SETUP_ACTIVITY); 1026ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } catch (ActivityNotFoundException e) { 1036ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko Log.e(TAG, "Can't find activity: " + setupIntent.getComponent()); 1046ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko finish(); 1056ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return; 1066ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 1076ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (needToFetchEpg) { 1086ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (sScanTimeoutMonitor == null) { 1096ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko sScanTimeoutMonitor = new ScanTimeoutMonitor(this); 1106ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 1116ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko sScanTimeoutMonitor.startMonitoring(); 1126ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko EpgFetcher.getInstance(this).onChannelScanStarted(); 1136ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 114721bd0da688cd552737fbb753a00597f95103b95Adrian Roos } 115721bd0da688cd552737fbb753a00597f95103b95Adrian Roos } 116721bd0da688cd552737fbb753a00597f95103b95Adrian Roos 117721bd0da688cd552737fbb753a00597f95103b95Adrian Roos @Override 1181abddd9f6225298066094e20a6c29061b6af4590Nick Chalko public void onActivityResult(int requestCode, final int resultCode, final Intent data) { 1196ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (DEBUG) Log.d(TAG, "onActivityResult"); 1206ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (sScanTimeoutMonitor != null) { 1216ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko sScanTimeoutMonitor.stopMonitoring(); 1226ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 1236ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko // Note: It's not guaranteed that this method is always called after scanning. 124ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko boolean setupComplete = requestCode == REQUEST_START_SETUP_ACTIVITY 125ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko && resultCode == Activity.RESULT_OK; 1266ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko // Tells EpgFetcher that channel source setup is finished. 1276ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (mEpgFetcherDuringScan) { 1286ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko EpgFetcher.getInstance(this).onChannelScanFinished(); 1296ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 130ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko if (!setupComplete) { 1311abddd9f6225298066094e20a6c29061b6af4590Nick Chalko setResult(resultCode, data); 1327d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko finish(); 1337d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko return; 1347d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1357d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko SetupUtils.getInstance(this).onTvInputSetupFinished(mTvInputInfo.getId(), new Runnable() { 1367d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko @Override 1377d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko public void run() { 1387d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (mActivityAfterCompletion != null) { 1397d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko try { 1407d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko startActivity(mActivityAfterCompletion); 1417d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } catch (ActivityNotFoundException e) { 1427d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko Log.w(TAG, "Activity launch failed", e); 1437d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1447d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1451abddd9f6225298066094e20a6c29061b6af4590Nick Chalko setResult(resultCode, data); 1467d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko finish(); 1477d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1487d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko }); 1497d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1506ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 1516ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko /** 1526ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko * Monitors the scan progress and notifies the timeout of the scanning. 1536ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko * The purpose of this monitor is to call EpgFetcher.onChannelScanFinished() in case when 1546ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko * SetupPassthroughActivity.onActivityResult() is not called properly. b/36008534 1556ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko */ 1566ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko @MainThread 1576ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko private static class ScanTimeoutMonitor { 1586ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko // Set timeout long enough. The message in Sony TV says the scanning takes about 30 minutes. 1596ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko private static final long SCAN_TIMEOUT_MS = TimeUnit.MINUTES.toMillis(30); 1606ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 1616ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko private final Context mContext; 1626ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko private final ChannelDataManager mChannelDataManager; 1636ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko private final Handler mHandler = new Handler(Looper.getMainLooper()); 1646ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko private final Runnable mScanTimeoutRunnable = new Runnable() { 1656ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko @Override 1666ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko public void run() { 1676ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko Log.w(TAG, "No channels has been added for a while." + 1686ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko " The scan might have finished unexpectedly."); 1696ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko onScanTimedOut(); 1706ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 1716ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko }; 1726ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko private final Listener mChannelDataManagerListener = new Listener() { 1736ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko @Override 1746ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko public void onLoadFinished() { 1756ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko setupTimer(); 1766ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 1776ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 1786ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko @Override 1796ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko public void onChannelListUpdated() { 1806ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko setupTimer(); 1816ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 1826ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 1836ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko @Override 1846ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko public void onChannelBrowsableChanged() { } 1856ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko }; 1866ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko private boolean mStarted; 1876ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 1886ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko private ScanTimeoutMonitor(Context context) { 1896ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mContext = context.getApplicationContext(); 1906ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mChannelDataManager = TvApplication.getSingletons(context).getChannelDataManager(); 1916ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 1926ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 1936ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko private void startMonitoring() { 1946ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (!mStarted) { 1956ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mStarted = true; 1966ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mChannelDataManager.addListener(mChannelDataManagerListener); 1976ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 1986ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (mChannelDataManager.isDbLoadFinished()) { 1996ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko setupTimer(); 2006ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 2016ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 2026ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 2036ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko private void stopMonitoring() { 2046ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (mStarted) { 2056ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mStarted = false; 2066ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mHandler.removeCallbacks(mScanTimeoutRunnable); 2076ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mChannelDataManager.removeListener(mChannelDataManagerListener); 2086ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 2096ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 2106ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 2116ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko private void setupTimer() { 2126ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mHandler.removeCallbacks(mScanTimeoutRunnable); 2136ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mHandler.postDelayed(mScanTimeoutRunnable, SCAN_TIMEOUT_MS); 2146ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 2156ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 2166ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko private void onScanTimedOut() { 2176ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko stopMonitoring(); 2186ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko EpgFetcher.getInstance(mContext).onChannelScanFinished(); 2196ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 2206ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 221721bd0da688cd552737fbb753a00597f95103b95Adrian Roos} 222