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