1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.quicksearchbox.google 17 18 import android.app.SearchManager 19 import android.content.ContentProvider 20 import android.content.ContentValues 21 import android.content.Context 22 import android.content.UriMatcher 23 import android.database.Cursor 24 import android.net.Uri 25 import android.util.Log 26 import com.android.quicksearchbox.CursorBackedSourceResult 27 import com.android.quicksearchbox.QsbApplication 28 import com.android.quicksearchbox.SourceResult 29 import com.android.quicksearchbox.SuggestionCursorBackedCursor 30 31 /** 32 * A suggestion provider which provides content from Genie, a service that offers a superset of the 33 * content provided by Google Suggest. 34 */ 35 class GoogleSuggestionProvider : ContentProvider() { 36 private var mUriMatcher: UriMatcher? = null 37 private var mSource: GoogleSource? = null 38 39 @Override onCreatenull40 override fun onCreate(): Boolean { 41 mSource = QsbApplication.get(getContext()).googleSource 42 mUriMatcher = buildUriMatcher(getContext()) 43 return true 44 } 45 46 /** 47 * This will always return [SearchManager.SUGGEST_MIME_TYPE] as this provider is purely to provide 48 * suggestions. 49 */ 50 @Override getTypenull51 override fun getType(uri: Uri): String? { 52 return SearchManager.SUGGEST_MIME_TYPE 53 } 54 emptyIfNullnull55 private fun emptyIfNull( 56 result: SourceResult?, 57 source: GoogleSource?, 58 query: String? 59 ): SourceResult { 60 return result ?: CursorBackedSourceResult(source, query) 61 } 62 63 @Override querynull64 override fun query( 65 uri: Uri, 66 projection: Array<String?>?, 67 selection: String?, 68 selectionArgs: Array<String?>?, 69 sortOrder: String? 70 ): Cursor { 71 if (GoogleSuggestionProvider.Companion.DBG) 72 Log.d(GoogleSuggestionProvider.Companion.TAG, "query uri=$uri") 73 val match: Int? = mUriMatcher?.match(uri) 74 return if (match == GoogleSuggestionProvider.Companion.SEARCH_SUGGEST) { 75 val query = getQuery(uri) 76 SuggestionCursorBackedCursor(emptyIfNull(mSource!!.queryExternal(query), mSource, query)) 77 } else if (match == GoogleSuggestionProvider.Companion.SEARCH_SHORTCUT) { 78 val shortcutId = getQuery(uri) 79 val extraData: String? = uri.getQueryParameter(SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA) 80 SuggestionCursorBackedCursor(mSource!!.refreshShortcut(shortcutId, extraData)) 81 } else { 82 throw IllegalArgumentException("Unknown URI $uri") 83 } 84 } 85 86 /** Gets the search text from a uri. */ getQuerynull87 private fun getQuery(uri: Uri): String? { 88 return if (uri.getPathSegments().size > 1) { 89 uri.getLastPathSegment() 90 } else { 91 "" 92 } 93 } 94 95 @Override insertnull96 override fun insert(uri: Uri, values: ContentValues?): Uri? { 97 throw UnsupportedOperationException() 98 } 99 100 @Override updatenull101 override fun update( 102 uri: Uri, 103 values: ContentValues?, 104 selection: String?, 105 selectionArgs: Array<String?>? 106 ): Int { 107 throw UnsupportedOperationException() 108 } 109 110 @Override deletenull111 override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String?>?): Int { 112 throw UnsupportedOperationException() 113 } 114 buildUriMatchernull115 private fun buildUriMatcher(context: Context?): UriMatcher { 116 val authority = getAuthority(context) 117 val matcher = UriMatcher(UriMatcher.NO_MATCH) 118 matcher.addURI( 119 authority, 120 SearchManager.SUGGEST_URI_PATH_QUERY, 121 GoogleSuggestionProvider.Companion.SEARCH_SUGGEST 122 ) 123 matcher.addURI( 124 authority, 125 SearchManager.SUGGEST_URI_PATH_QUERY.toString() + "/*", 126 GoogleSuggestionProvider.Companion.SEARCH_SUGGEST 127 ) 128 matcher.addURI( 129 authority, 130 SearchManager.SUGGEST_URI_PATH_SHORTCUT, 131 GoogleSuggestionProvider.Companion.SEARCH_SHORTCUT 132 ) 133 matcher.addURI( 134 authority, 135 SearchManager.SUGGEST_URI_PATH_SHORTCUT.toString() + "/*", 136 GoogleSuggestionProvider.Companion.SEARCH_SHORTCUT 137 ) 138 return matcher 139 } 140 getAuthoritynull141 protected fun getAuthority(context: Context?): String { 142 return context?.getPackageName().toString() + ".google" 143 } 144 145 companion object { 146 private const val DBG = false 147 private const val TAG = "QSB.GoogleSuggestionProvider" 148 149 // UriMatcher constants 150 private const val SEARCH_SUGGEST = 0 151 private const val SEARCH_SHORTCUT = 1 152 } 153 } 154