1 /* 2 * Copyright (C) 2015 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.settings.applications; 18 19 import android.content.ComponentName; 20 import android.content.ContentResolver; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.pm.ApplicationInfo; 24 import android.content.pm.PackageInfo; 25 import android.content.pm.PackageManager; 26 import android.content.pm.ResolveInfo; 27 import android.os.AsyncTask; 28 import android.provider.Settings; 29 import android.telephony.TelephonyManager; 30 import android.text.TextUtils; 31 import android.util.ArraySet; 32 import android.util.AttributeSet; 33 import com.android.internal.telephony.SmsApplication; 34 import com.android.settings.AppListPreference; 35 import com.android.settings.SelfAvailablePreference; 36 37 import java.util.List; 38 import java.util.Objects; 39 import java.util.Set; 40 41 /** 42 * A preference for choosing the default emergency app 43 */ 44 public class DefaultEmergencyPreference extends AppListPreference 45 implements SelfAvailablePreference { 46 47 private static final boolean DEFAULT_EMERGENCY_APP_IS_CONFIGURABLE = false; 48 private final ContentResolver mContentResolver; 49 50 public static final Intent QUERY_INTENT = new Intent( 51 TelephonyManager.ACTION_EMERGENCY_ASSISTANCE); 52 DefaultEmergencyPreference(Context context, AttributeSet attrs)53 public DefaultEmergencyPreference(Context context, AttributeSet attrs) { 54 super(context, attrs); 55 mContentResolver = context.getContentResolver(); 56 load(); 57 } 58 59 @Override persistString(String value)60 protected boolean persistString(String value) { 61 String previousValue = Settings.Secure.getString(mContentResolver, 62 Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION); 63 64 if (!TextUtils.isEmpty(value) && !Objects.equals(value, previousValue)) { 65 Settings.Secure.putString(mContentResolver, 66 Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION, 67 value); 68 } 69 setSummary(getEntry()); 70 return true; 71 } 72 load()73 private void load() { 74 new AsyncTask<Void, Void, Set<String>>() { 75 @Override 76 protected Set<String> doInBackground(Void[] params) { 77 return resolveAssistPackageAndQueryApps(); 78 } 79 80 @Override 81 protected void onPostExecute(Set<String> entries) { 82 String currentPkg = Settings.Secure.getString(mContentResolver, 83 Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION); 84 setPackageNames(entries.toArray(new String[entries.size()]), currentPkg); 85 } 86 }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 87 } 88 resolveAssistPackageAndQueryApps()89 private Set<String> resolveAssistPackageAndQueryApps() { 90 Set<String> packages = new ArraySet<>(); 91 92 PackageManager packageManager = getContext().getPackageManager(); 93 List<ResolveInfo> infos = packageManager.queryIntentActivities(QUERY_INTENT, 0); 94 95 PackageInfo bestMatch = null; 96 final int size = infos.size(); 97 for (int i = 0; i < size; i++) { 98 ResolveInfo info = infos.get(i); 99 if (info == null || info.activityInfo == null 100 || packages.contains(info.activityInfo.packageName)) { 101 continue; 102 } 103 104 String packageName = info.activityInfo.packageName; 105 106 packages.add(packageName); 107 108 PackageInfo packageInfo; 109 try { 110 packageInfo = packageManager.getPackageInfo(packageName, 0); 111 } catch (PackageManager.NameNotFoundException e) { 112 continue; 113 } 114 115 // Get earliest installed system app. 116 if (isSystemApp(packageInfo) && (bestMatch == null || 117 bestMatch.firstInstallTime > packageInfo.firstInstallTime)) { 118 bestMatch = packageInfo; 119 } 120 } 121 122 String defaultPackage = Settings.Secure.getString(mContentResolver, 123 Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION); 124 boolean defaultMissing = TextUtils.isEmpty(defaultPackage) 125 || !packages.contains(defaultPackage); 126 if (bestMatch != null && defaultMissing) { 127 Settings.Secure.putString(mContentResolver, 128 Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION, 129 bestMatch.packageName); 130 } 131 132 return packages; 133 } 134 isCapable(Context context)135 private static boolean isCapable(Context context) { 136 return TelephonyManager.EMERGENCY_ASSISTANCE_ENABLED 137 && context.getResources().getBoolean( 138 com.android.internal.R.bool.config_voice_capable); 139 } 140 isSystemApp(PackageInfo info)141 private static boolean isSystemApp(PackageInfo info) { 142 return info.applicationInfo != null 143 && (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; 144 } 145 isAvailable(Context context)146 public boolean isAvailable(Context context) { 147 return DEFAULT_EMERGENCY_APP_IS_CONFIGURABLE 148 && isCapable(context) 149 && context.getPackageManager().resolveActivity(QUERY_INTENT, 0) != null; 150 } 151 hasEmergencyPreference(String pkg, Context context)152 public static boolean hasEmergencyPreference(String pkg, Context context) { 153 Intent i = new Intent(QUERY_INTENT); 154 i.setPackage(pkg); 155 final List<ResolveInfo> resolveInfos = 156 context.getPackageManager().queryIntentActivities(i, 0); 157 return resolveInfos != null && resolveInfos.size() != 0; 158 } 159 isEmergencyDefault(String pkg, Context context)160 public static boolean isEmergencyDefault(String pkg, Context context) { 161 String defaultPackage = Settings.Secure.getString(context.getContentResolver(), 162 Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION); 163 return defaultPackage != null && defaultPackage.equals(pkg); 164 } 165 } 166