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.search; 187d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 197d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport android.content.Context; 207d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport android.content.Intent; 217d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport android.media.tv.TvContentRating; 227d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport android.media.tv.TvContract; 237d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport android.media.tv.TvContract.Programs; 247d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport android.media.tv.TvInputManager; 25ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport android.support.annotation.MainThread; 267d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport android.text.TextUtils; 277d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport android.util.Log; 287d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 291abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.android.tv.ApplicationSingletons; 307d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport com.android.tv.TvApplication; 317d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport com.android.tv.data.Channel; 327d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport com.android.tv.data.ChannelDataManager; 337d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport com.android.tv.data.Program; 347d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport com.android.tv.data.ProgramDataManager; 357d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport com.android.tv.search.LocalSearchProvider.SearchResult; 367d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport com.android.tv.util.MainThreadExecutor; 377d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport com.android.tv.util.Utils; 387d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 397d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport java.util.ArrayList; 407d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport java.util.Collections; 417d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport java.util.HashSet; 427d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport java.util.List; 437d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport java.util.Set; 447d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport java.util.concurrent.Callable; 457d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport java.util.concurrent.ExecutionException; 467d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport java.util.concurrent.Future; 477d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 487d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko/** 497d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * An implementation of {@link SearchInterface} to search query from {@link ChannelDataManager} 507d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * and {@link ProgramDataManager}. 517d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko */ 527d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkopublic class DataManagerSearch implements SearchInterface { 537d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko private static final boolean DEBUG = false; 547d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko private static final String TAG = "TvProviderSearch"; 557d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 567d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko private final Context mContext; 577d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko private final TvInputManager mTvInputManager; 587d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko private final ChannelDataManager mChannelDataManager; 597d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko private final ProgramDataManager mProgramDataManager; 607d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 617d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko DataManagerSearch(Context context) { 627d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko mContext = context; 637d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko mTvInputManager = (TvInputManager) context.getSystemService(Context.TV_INPUT_SERVICE); 641abddd9f6225298066094e20a6c29061b6af4590Nick Chalko ApplicationSingletons appSingletons = TvApplication.getSingletons(context); 651abddd9f6225298066094e20a6c29061b6af4590Nick Chalko mChannelDataManager = appSingletons.getChannelDataManager(); 661abddd9f6225298066094e20a6c29061b6af4590Nick Chalko mProgramDataManager = appSingletons.getProgramDataManager(); 677d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 687d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 697d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko @Override 707d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko public List<SearchResult> search(final String query, final int limit, final int action) { 717d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko Future<List<SearchResult>> future = MainThreadExecutor.getInstance() 727d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko .submit(new Callable<List<SearchResult>>() { 737d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko @Override 747d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko public List<SearchResult> call() throws Exception { 757d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko return searchFromDataManagers(query, limit, action); 767d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 777d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko }); 787d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 797d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko try { 807d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko return future.get(); 817d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } catch (InterruptedException e) { 827d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko Thread.interrupted(); 837d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko return Collections.EMPTY_LIST; 847d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } catch (ExecutionException e) { 857d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko Log.w(TAG, "Error searching for " + query, e); 867d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko return Collections.EMPTY_LIST; 877d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 887d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 897d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 90ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko @MainThread 917d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko private List<SearchResult> searchFromDataManagers(String query, int limit, int action) { 927d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko List<SearchResult> results = new ArrayList<>(); 937d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (!mChannelDataManager.isDbLoadFinished()) { 947d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko return results; 957d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 967d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (action == ACTION_TYPE_SWITCH_CHANNEL 977d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko || action == ACTION_TYPE_SWITCH_INPUT) { 987d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko // Voice search query should be handled by the a system TV app. 997d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko return results; 1007d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1017d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko Set<Long> channelsFound = new HashSet<>(); 1027d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko List<Channel> channelList = mChannelDataManager.getBrowsableChannelList(); 1037d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko query = query.toLowerCase(); 1047d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (TextUtils.isDigitsOnly(query)) { 1057d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko for (Channel channel : channelList) { 1067d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (channelsFound.contains(channel.getId())) { 1077d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko continue; 1087d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1097d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (contains(channel.getDisplayNumber(), query)) { 1107d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko addResult(results, channelsFound, channel, null); 1117d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1127d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (results.size() >= limit) { 1137d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko return results; 1147d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1157d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1167d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko // TODO: recently watched channels may have higher priority. 1177d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1187d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko for (Channel channel : channelList) { 1197d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (channelsFound.contains(channel.getId())) { 1207d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko continue; 1217d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1227d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (contains(channel.getDisplayName(), query) 1237d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko || contains(channel.getDescription(), query)) { 1247d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko addResult(results, channelsFound, channel, null); 1257d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1267d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (results.size() >= limit) { 1277d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko return results; 1287d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1297d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1307d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko for (Channel channel : channelList) { 1317d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (channelsFound.contains(channel.getId())) { 1327d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko continue; 1337d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1347d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko Program program = mProgramDataManager.getCurrentProgram(channel.getId()); 1357d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (program == null) { 1367d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko continue; 1377d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1387d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (contains(program.getTitle(), query) 1397d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko && !isRatingBlocked(program.getContentRatings())) { 1407d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko addResult(results, channelsFound, channel, program); 1417d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1427d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (results.size() >= limit) { 1437d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko return results; 1447d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1457d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1467d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko for (Channel channel : channelList) { 1477d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (channelsFound.contains(channel.getId())) { 1487d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko continue; 1497d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1507d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko Program program = mProgramDataManager.getCurrentProgram(channel.getId()); 1517d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (program == null) { 1527d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko continue; 1537d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1547d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (contains(program.getDescription(), query) 1557d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko && !isRatingBlocked(program.getContentRatings())) { 1567d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko addResult(results, channelsFound, channel, program); 1577d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1587d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (results.size() >= limit) { 1597d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko return results; 1607d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1617d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1627d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko return results; 1637d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1647d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 1657d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko // It assumes that query is already lower cases. 1667d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko private boolean contains(String string, String query) { 1677d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko return string != null && string.toLowerCase().contains(query); 1687d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1697d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 1707d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko /** 1717d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * If query is matched to channel, {@code program} should be null. 1727d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko */ 1737d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko private void addResult(List<SearchResult> results, Set<Long> channelsFound, Channel channel, 1747d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko Program program) { 1757d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (program == null) { 1767d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko program = mProgramDataManager.getCurrentProgram(channel.getId()); 1777d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (program != null && isRatingBlocked(program.getContentRatings())) { 1787d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko program = null; 1797d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1807d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1817d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 1827d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko SearchResult result = new SearchResult(); 1837d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 1847d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko long channelId = channel.getId(); 1857d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko result.channelId = channelId; 1867d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko result.channelNumber = channel.getDisplayNumber(); 1877d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (program == null) { 1887d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko result.title = channel.getDisplayName(); 1897d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko result.description = channel.getDescription(); 1907d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko result.imageUri = TvContract.buildChannelLogoUri(channelId).toString(); 1917d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko result.intentAction = Intent.ACTION_VIEW; 1927d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko result.intentData = buildIntentData(channelId); 1937d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko result.contentType = Programs.CONTENT_ITEM_TYPE; 1947d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko result.isLive = true; 1957d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko result.progressPercentage = LocalSearchProvider.PROGRESS_PERCENTAGE_HIDE; 1967d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } else { 1977d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko result.title = program.getTitle(); 1987d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko result.description = buildProgramDescription(channel.getDisplayNumber(), 1997d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko channel.getDisplayName(), program.getStartTimeUtcMillis(), 2007d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko program.getEndTimeUtcMillis()); 2017d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko result.imageUri = program.getPosterArtUri(); 2027d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko result.intentAction = Intent.ACTION_VIEW; 2037d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko result.intentData = buildIntentData(channelId); 2047d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko result.contentType = Programs.CONTENT_ITEM_TYPE; 2057d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko result.isLive = true; 2067d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko result.videoWidth = program.getVideoWidth(); 2077d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko result.videoHeight = program.getVideoHeight(); 2087d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko result.duration = program.getDurationMillis(); 2097d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko result.progressPercentage = getProgressPercentage( 2107d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko program.getStartTimeUtcMillis(), program.getEndTimeUtcMillis()); 2117d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 2127d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (DEBUG) { 2137d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko Log.d(TAG, "Add a result : channel=" + channel + " program=" + program); 2147d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 2157d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko results.add(result); 2167d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko channelsFound.add(channel.getId()); 2177d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 2187d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 2197d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko private String buildProgramDescription(String channelNumber, String channelName, 2207d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko long programStartUtcMillis, long programEndUtcMillis) { 2217d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko return Utils.getDurationString(mContext, programStartUtcMillis, programEndUtcMillis, false) 2227d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko + System.lineSeparator() + channelNumber + " " + channelName; 2237d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 2247d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 2257d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko private int getProgressPercentage(long startUtcMillis, long endUtcMillis) { 2267d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko long current = System.currentTimeMillis(); 2277d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (startUtcMillis > current || endUtcMillis <= current) { 2287d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko return LocalSearchProvider.PROGRESS_PERCENTAGE_HIDE; 2297d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 2307d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko return (int)(100 * (current - startUtcMillis) / (endUtcMillis - startUtcMillis)); 2317d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 2327d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 2337d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko private String buildIntentData(long channelId) { 2347d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko return TvContract.buildChannelUri(channelId).buildUpon() 2357d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko .appendQueryParameter(Utils.PARAM_SOURCE, SOURCE_TV_SEARCH) 2367d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko .build().toString(); 2377d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 2387d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 2397d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko private boolean isRatingBlocked(TvContentRating[] ratings) { 2407d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (ratings == null || ratings.length == 0 2417d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko || !mTvInputManager.isParentalControlsEnabled()) { 2427d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko return false; 2437d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 2447d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko for (TvContentRating rating : ratings) { 2457d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko try { 2467d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (mTvInputManager.isRatingBlocked(rating)) { 2477d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko return true; 2487d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 2497d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } catch (IllegalArgumentException e) { 2507d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko // Do nothing. 2517d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 2527d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 2537d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko return false; 2547d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 2557d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko} 256