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