1 /*
2  * Copyright 2024 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 
17 package com.android.systemui.emergency
18 
19 import android.content.ComponentName
20 import android.content.Intent
21 import android.content.pm.PackageManager
22 import android.content.pm.ResolveInfo
23 import android.content.res.Resources
24 import android.text.TextUtils
25 import android.util.Log
26 import dagger.Module
27 import dagger.Provides
28 
29 import com.android.systemui.dagger.qualifiers.Main
30 import com.android.systemui.res.R
31 
32 /** Module for providing emergency gesture objects. */
33 @Module
34 object EmergencyGestureModule {
35 
36     val TAG: String = "EmergencyGestureModule"
37 
38     @Provides
emergencyGestureIntentFactorynull39     fun emergencyGestureIntentFactory(
40         packageManager: PackageManager,
41         @Main resources: Resources,
42     ): EmergencyGestureIntentFactory {
43         return object : EmergencyGestureIntentFactory {
44             override fun invoke(action: String): Intent? {
45                 return getEmergencyActionIntent(packageManager, resources, action)
46             }
47         }
48     }
49 
50     /**
51      * Return the "best" Emergency action intent for a given action
52      */
getEmergencyActionIntentnull53     private fun getEmergencyActionIntent(
54         packageManager: PackageManager,
55         @Main resources: Resources,
56         action: String,
57     ): Intent? {
58         val emergencyIntent = Intent(action)
59         val emergencyActivities = packageManager.queryIntentActivities(emergencyIntent,
60                 PackageManager.MATCH_SYSTEM_ONLY)
61         val resolveInfo: ResolveInfo? = getTopEmergencySosInfo(emergencyActivities, resources)
62         if (resolveInfo == null) {
63             Log.wtf(TAG, "Couldn't find an app to process the emergency intent.")
64             return null
65         }
66         emergencyIntent.setComponent(ComponentName(resolveInfo.activityInfo.packageName,
67                 resolveInfo.activityInfo.name))
68         emergencyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
69         return emergencyIntent
70     }
71 
72     /**
73      * Select and return the "best" ResolveInfo for Emergency SOS Activity.
74      */
getTopEmergencySosInfonull75     private fun getTopEmergencySosInfo(
76         emergencyActivities: List<ResolveInfo>,
77         @Main resources: Resources,
78     ): ResolveInfo? {
79         // No matched activity.
80         if (emergencyActivities.isEmpty()) {
81             return null
82         }
83 
84         // Of multiple matched Activities, give preference to the pre-set package name.
85         val preferredAppPackageName =
86                 resources.getString(R.string.config_preferredEmergencySosPackage)
87 
88         // If there is no preferred app, then return first match.
89         if (TextUtils.isEmpty(preferredAppPackageName)) {
90             return emergencyActivities.get(0)
91         }
92 
93         for (emergencyInfo: ResolveInfo in emergencyActivities) {
94             // If activity is from the preferred app, use it.
95             if (TextUtils.equals(emergencyInfo.activityInfo.packageName, preferredAppPackageName)) {
96                 return emergencyInfo
97             }
98         }
99         // No matching activity: return first match
100         return emergencyActivities.get(0)
101     }
102 
103     /**
104      * Creates an intent to launch the Emergency action. If no handler is present, returns `null`.
105      */
106     public interface EmergencyGestureIntentFactory {
invokenull107         operator fun invoke(action: String): Intent?
108     }
109 }
110