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