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