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.content.pm.ComponentInfo
23 import android.content.pm.PackageManager
24 import android.content.pm.PackageManager.NameNotFoundException
25 import android.content.pm.ResolveInfo
26 import android.os.Bundle
27 import android.speech.RecognizerIntent
28 import android.util.Log
29 
30 /** Voice Search integration. */
31 class VoiceSearch(context: Context?) {
32 
33   private val mContext: Context?
34 
35   protected val context: Context?
36     get() = mContext
37 
shouldShowVoiceSearchnull38   fun shouldShowVoiceSearch(): Boolean {
39     return isVoiceSearchAvailable
40   }
41 
createVoiceSearchIntentnull42   protected fun createVoiceSearchIntent(): Intent {
43     return Intent(RecognizerIntent.ACTION_WEB_SEARCH)
44   }
45 
46   private val resolveInfo: ResolveInfo?
47     @Suppress("DEPRECATION")
48     get() {
49       val intent: Intent = createVoiceSearchIntent()
50       return mContext
51         ?.getPackageManager()
52         ?.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY)
53     }
54   val isVoiceSearchAvailable: Boolean
55     get() = resolveInfo != null
56 
createVoiceWebSearchIntentnull57   fun createVoiceWebSearchIntent(appData: Bundle?): Intent? {
58     if (!isVoiceSearchAvailable) return null
59     val intent: Intent = createVoiceSearchIntent()
60     intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
61     intent.putExtra(
62       RecognizerIntent.EXTRA_LANGUAGE_MODEL,
63       RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH
64     )
65     if (appData != null) {
66       intent.putExtra(SearchManager.APP_DATA, appData)
67     }
68     return intent
69   }
70 
71   /**
72    * Create an intent to launch the voice search help screen, if any exists.
73    * @return The intent, or null.
74    */
createVoiceSearchHelpIntentnull75   fun createVoiceSearchHelpIntent(): Intent? {
76     return null
77   }
78 
79   /**
80    * Gets the `versionCode` of the currently installed voice search package.
81    *
82    * @return The `versionCode` of voiceSearch, or 0 if none is installed.
83    */
84   val version: Long
85     @Suppress("DEPRECATION")
86     get() {
87       val ri: ResolveInfo = resolveInfo ?: return 0
88       val ci: ComponentInfo = if (ri.activityInfo != null) ri.activityInfo else ri.serviceInfo
89       return try {
90         context!!.getPackageManager().getPackageInfo(ci.packageName, 0).getLongVersionCode()
91       } catch (e: NameNotFoundException) {
92         Log.e(TAG, "Cannot find voice search package " + ci.packageName, e)
93         0
94       }
95     }
96   val component: ComponentName
97     get() = createVoiceSearchIntent().resolveActivity(context!!.getPackageManager())
98 
99   companion object {
100     private const val TAG = "QSB.VoiceSearch"
101   }
102 
103   init {
104     mContext = context
105   }
106 }
107