| /* |
| * Copyright (C) 2015 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.tv.search; |
| |
| import android.app.SearchManager; |
| import android.content.ContentProvider; |
| import android.content.ContentValues; |
| import android.database.Cursor; |
| import android.database.MatrixCursor; |
| import android.net.Uri; |
| import android.os.SystemClock; |
| import android.text.TextUtils; |
| import android.util.Log; |
| |
| import com.android.tv.util.PermissionUtils; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.List; |
| |
| public class LocalSearchProvider extends ContentProvider { |
| private static final String TAG = "LocalSearchProvider"; |
| private static final boolean DEBUG = false; |
| |
| public static final int PROGRESS_PERCENTAGE_HIDE = -1; |
| |
| // TODO: Remove this once added to the SearchManager. |
| private static final String SUGGEST_COLUMN_PROGRESS_BAR_PERCENTAGE = "progress_bar_percentage"; |
| |
| private static final String[] SEARCHABLE_COLUMNS = new String[] { |
| SearchManager.SUGGEST_COLUMN_TEXT_1, |
| SearchManager.SUGGEST_COLUMN_TEXT_2, |
| SearchManager.SUGGEST_COLUMN_RESULT_CARD_IMAGE, |
| SearchManager.SUGGEST_COLUMN_INTENT_ACTION, |
| SearchManager.SUGGEST_COLUMN_INTENT_DATA, |
| SearchManager.SUGGEST_COLUMN_CONTENT_TYPE, |
| SearchManager.SUGGEST_COLUMN_IS_LIVE, |
| SearchManager.SUGGEST_COLUMN_VIDEO_WIDTH, |
| SearchManager.SUGGEST_COLUMN_VIDEO_HEIGHT, |
| SearchManager.SUGGEST_COLUMN_DURATION, |
| SUGGEST_COLUMN_PROGRESS_BAR_PERCENTAGE |
| }; |
| |
| private static final String EXPECTED_PATH_PREFIX = "/" + SearchManager.SUGGEST_URI_PATH_QUERY; |
| // The launcher passes 10 as a 'limit' parameter by default. |
| private static final int DEFAULT_SEARCH_LIMIT = 10; |
| |
| private static final String NO_LIVE_CONTENTS = "0"; |
| private static final String LIVE_CONTENTS = "1"; |
| |
| static final String SUGGEST_PARAMETER_ACTION = "action"; |
| static final int DEFAULT_SEARCH_ACTION = SearchInterface.ACTION_TYPE_AMBIGUOUS; |
| |
| @Override |
| public boolean onCreate() { |
| return true; |
| } |
| |
| @Override |
| public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, |
| String sortOrder) { |
| if (DEBUG) { |
| Log.d(TAG, "query(" + uri + ", " + Arrays.toString(projection) + ", " + selection + ", " |
| + Arrays.toString(selectionArgs) + ", " + sortOrder + ")"); |
| } |
| long time = SystemClock.elapsedRealtime(); |
| SearchInterface search; |
| if (PermissionUtils.hasAccessAllEpg(getContext())) { |
| if (DEBUG) Log.d(TAG, "Performing TV Provider search."); |
| search = new TvProviderSearch(getContext()); |
| } else { |
| if (DEBUG) Log.d(TAG, "Performing Data Manager search."); |
| search = new DataManagerSearch(getContext()); |
| } |
| String query = uri.getLastPathSegment(); |
| int limit = DEFAULT_SEARCH_LIMIT; |
| int action = DEFAULT_SEARCH_ACTION; |
| try { |
| limit = Integer.parseInt(uri.getQueryParameter(SearchManager.SUGGEST_PARAMETER_LIMIT)); |
| action = Integer.parseInt(uri.getQueryParameter(SUGGEST_PARAMETER_ACTION)); |
| } catch (NumberFormatException | UnsupportedOperationException e) { |
| // Ignore the exceptions |
| } |
| List<SearchResult> results = new ArrayList<>(); |
| if (!TextUtils.isEmpty(query)) { |
| results.addAll(search.search(query, limit, action)); |
| } |
| Cursor c = createSuggestionsCursor(results); |
| if (DEBUG) Log.d(TAG, "Elapsed time: " + (SystemClock.elapsedRealtime() - time) + "(msec)"); |
| return c; |
| } |
| |
| private Cursor createSuggestionsCursor(List<SearchResult> results) { |
| MatrixCursor cursor = new MatrixCursor(SEARCHABLE_COLUMNS, results.size()); |
| List<String> row = new ArrayList<>(SEARCHABLE_COLUMNS.length); |
| |
| for (SearchResult result : results) { |
| row.clear(); |
| row.add(result.title); |
| row.add(result.description); |
| row.add(result.imageUri); |
| row.add(result.intentAction); |
| row.add(result.intentData); |
| row.add(result.contentType); |
| row.add(result.isLive ? LIVE_CONTENTS : NO_LIVE_CONTENTS); |
| row.add(result.videoWidth == 0 ? null : String.valueOf(result.videoWidth)); |
| row.add(result.videoHeight == 0 ? null : String.valueOf(result.videoHeight)); |
| row.add(result.duration == 0 ? null : String.valueOf(result.duration)); |
| row.add(String.valueOf(result.progressPercentage)); |
| cursor.addRow(row); |
| } |
| return cursor; |
| } |
| |
| @Override |
| public String getType(Uri uri) { |
| if (!checkUriCorrect(uri)) return null; |
| return SearchManager.SUGGEST_MIME_TYPE; |
| } |
| |
| private static boolean checkUriCorrect(Uri uri) { |
| return uri != null && uri.getPath().startsWith(EXPECTED_PATH_PREFIX); |
| } |
| |
| @Override |
| public Uri insert(Uri uri, ContentValues values) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public int delete(Uri uri, String selection, String[] selectionArgs) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| /** |
| * A placeholder to a search result. |
| */ |
| public static class SearchResult { |
| public long channelId; |
| public String channelNumber; |
| public String title; |
| public String description; |
| public String imageUri; |
| public String intentAction; |
| public String intentData; |
| public String contentType; |
| public boolean isLive; |
| public int videoWidth; |
| public int videoHeight; |
| public long duration; |
| public int progressPercentage; |
| |
| @Override |
| public String toString() { |
| return "channelId: " + channelId + |
| ", channelNumber: " + channelNumber + |
| ", title: " + title; |
| } |
| } |
| } |