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 17 18 import android.app.SearchManager 19 import android.content.ComponentName 20 import android.content.Context 21 import android.content.Intent 22 import android.graphics.drawable.Drawable 23 import android.net.Uri 24 import android.os.Bundle 25 import android.os.Handler 26 import android.util.Log 27 import com.android.quicksearchbox.util.NamedTaskExecutor 28 import com.android.quicksearchbox.util.NowOrLater 29 30 /** Abstract suggestion source implementation. */ 31 abstract class AbstractSource( 32 context: Context?, 33 uiThread: Handler?, 34 iconLoader: NamedTaskExecutor 35 ) : Source { 36 private val mContext: Context? 37 private val mUiThread: Handler? 38 private var mIconLoader: IconLoader? = null 39 private val mIconLoaderExecutor: NamedTaskExecutor 40 protected val context: Context? 41 get() = mContext 42 protected val iconLoader: IconLoader? 43 get() { 44 if (mIconLoader == null) { 45 val iconPackage = iconPackage 46 mIconLoader = 47 CachingIconLoader( 48 PackageIconLoader(mContext, iconPackage, mUiThread, mIconLoaderExecutor) 49 ) 50 } 51 return mIconLoader 52 } 53 protected abstract val iconPackage: String 54 55 @Override getIconnull56 override fun getIcon(drawableId: String?): NowOrLater<Drawable?>? { 57 return iconLoader?.getIcon(drawableId) 58 } 59 60 @Override getIconUrinull61 override fun getIconUri(drawableId: String?): Uri? { 62 return iconLoader?.getIconUri(drawableId) 63 } 64 65 @Override createSearchIntentnull66 override fun createSearchIntent(query: String?, appData: Bundle?): Intent? { 67 return createSourceSearchIntent(intentComponent, query, appData) 68 } 69 createVoiceWebSearchIntentnull70 protected fun createVoiceWebSearchIntent(appData: Bundle?): Intent? { 71 return QsbApplication.get(mContext).voiceSearch?.createVoiceWebSearchIntent(appData) 72 } 73 getRootnull74 override fun getRoot(): Source { 75 return this 76 } 77 78 @Override equalsnull79 override fun equals(other: Any?): Boolean { 80 if (other is Source) { 81 val s: Source = other.getRoot() 82 if (s::class == this::class) { 83 return s.name.equals(name) 84 } 85 } 86 return false 87 } 88 89 @Override hashCodenull90 override fun hashCode(): Int { 91 return name.hashCode() 92 } 93 94 @Override toStringnull95 override fun toString(): String { 96 return "Source{name=" + name.toString() + "}" 97 } 98 99 companion object { 100 private const val TAG = "QSB.AbstractSource" 101 102 @JvmStatic createSourceSearchIntentnull103 fun createSourceSearchIntent( 104 activity: ComponentName?, 105 query: String?, 106 appData: Bundle? 107 ): Intent? { 108 if (activity == null) { 109 Log.w(TAG, "Tried to create search intent with no target activity") 110 return null 111 } 112 val intent = Intent(Intent.ACTION_SEARCH) 113 intent.setComponent(activity) 114 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 115 // We need CLEAR_TOP to avoid reusing an old task that has other activities 116 // on top of the one we want. 117 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) 118 intent.putExtra(SearchManager.USER_QUERY, query) 119 intent.putExtra(SearchManager.QUERY, query) 120 if (appData != null) { 121 intent.putExtra(SearchManager.APP_DATA, appData) 122 } 123 return intent 124 } 125 } 126 127 init { 128 mContext = context 129 mUiThread = uiThread 130 mIconLoaderExecutor = iconLoader 131 } 132 } 133