blob: 4b291c522956ad6d969714b55ef20aa3470993a7 [file] [log] [blame]
Chihhang Chuangf264cfb2018-06-05 15:29:06 +08001/*
2 * Copyright (C) 2018 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
17package com.android.phone;
18
Hongming Jin862ce042019-02-05 15:42:50 -080019import android.app.role.RoleManager;
20import android.app.role.RoleManagerCallback;
Chihhang Chuangf264cfb2018-06-05 15:29:06 +080021import android.content.ComponentName;
22import android.content.Context;
23import android.content.Intent;
24import android.content.pm.ApplicationInfo;
25import android.content.pm.PackageInfo;
26import android.content.pm.PackageManager;
27import android.content.pm.ResolveInfo;
Hongming Jin862ce042019-02-05 15:42:50 -080028import android.os.AsyncTask;
29import android.os.Binder;
30import android.os.Process;
Chihhang Chuangf264cfb2018-06-05 15:29:06 +080031import android.telephony.TelephonyManager;
32import android.text.TextUtils;
yuanjiahsubc20ba82018-11-26 22:57:18 +080033import android.util.FeatureFlagUtils;
Hongming Jin862ce042019-02-05 15:42:50 -080034import android.util.Log;
35
36import com.android.internal.util.CollectionUtils;
Chihhang Chuangf264cfb2018-06-05 15:29:06 +080037
38import java.util.List;
39
40/**
41 * A helper to query activities of emergency assistance.
42 */
43public class EmergencyAssistanceHelper {
Hongming Jin862ce042019-02-05 15:42:50 -080044 private static final String TAG = EmergencyAssistanceHelper.class.getSimpleName();
Chihhang Chuangf264cfb2018-06-05 15:29:06 +080045 /**
yuanjiahsubc20ba82018-11-26 22:57:18 +080046 * Get intent action of target emergency app.
47 *
48 * @param context The context of the application.
49 * @return A string of intent action to launch target emergency app by feature flag, it will be
50 * used for team food.
51 */
52 public static String getIntentAction(Context context) {
yuanjiahsu8f3b1152019-03-13 15:33:23 +080053 String action = context.getResources().getString(R.string.config_emergency_app_intent);
54 if (!action.isEmpty()) {
55 // TODO: remove feature flag and this temporary intent once Emergency app was replaced.
56 if (!FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.SAFETY_HUB)) {
57 return "com.android.emergency.action.EMERGENCY_ASSISTANCE";
yuanjiahsubc20ba82018-11-26 22:57:18 +080058 }
yuanjiahsu8f3b1152019-03-13 15:33:23 +080059 return action;
yuanjiahsubc20ba82018-11-26 22:57:18 +080060 }
61
62 return TelephonyManager.ACTION_EMERGENCY_ASSISTANCE;
63 }
64
65 /**
Chihhang Chuangf264cfb2018-06-05 15:29:06 +080066 * Query activities of emergency assistance.
67 *
68 * @param context The context of the application.
69 * @return A list of {@link ResolveInfo} which is queried from default assistance package,
70 * or null if there is no installed system application of emergency assistance.
71 */
72 public static List<ResolveInfo> resolveAssistPackageAndQueryActivities(Context context) {
Hongming Jin862ce042019-02-05 15:42:50 -080073 final String assistPackage = getDefaultEmergencyPackage(context);
74 List<ResolveInfo> infos = queryAssistActivities(context, assistPackage);
Chihhang Chuangf264cfb2018-06-05 15:29:06 +080075 if (infos == null || infos.isEmpty()) {
76 PackageManager packageManager = context.getPackageManager();
yuanjiahsubc20ba82018-11-26 22:57:18 +080077 Intent queryIntent = new Intent(getIntentAction(context));
Chihhang Chuangf264cfb2018-06-05 15:29:06 +080078 infos = packageManager.queryIntentActivities(queryIntent, 0);
79
80 PackageInfo bestMatch = null;
81 for (int i = 0; i < infos.size(); i++) {
82 if (infos.get(i).activityInfo == null) continue;
83 String packageName = infos.get(i).activityInfo.packageName;
84 PackageInfo packageInfo;
85 try {
86 packageInfo = packageManager.getPackageInfo(packageName, 0);
87 } catch (PackageManager.NameNotFoundException e) {
88 continue;
89 }
90 // Get earliest installed system app.
91 if (isSystemApp(packageInfo) && (bestMatch == null
92 || bestMatch.firstInstallTime > packageInfo.firstInstallTime)) {
93 bestMatch = packageInfo;
94 }
95 }
96
97 if (bestMatch != null) {
Hongming Jin862ce042019-02-05 15:42:50 -080098 setDefaultEmergencyPackageAsync(context, bestMatch.packageName);
99 return queryAssistActivities(context, bestMatch.packageName);
Chihhang Chuangf264cfb2018-06-05 15:29:06 +0800100 } else {
101 return null;
102 }
103 } else {
104 return infos;
105 }
106 }
107
108 /**
109 * Compose {@link ComponentName} from {@link ResolveInfo}.
110 */
111 public static ComponentName getComponentName(ResolveInfo resolveInfo) {
112 if (resolveInfo == null || resolveInfo.activityInfo == null) return null;
113 return new ComponentName(resolveInfo.activityInfo.packageName,
114 resolveInfo.activityInfo.name);
115 }
116
Hongming Jin862ce042019-02-05 15:42:50 -0800117 private static List<ResolveInfo> queryAssistActivities(Context context, String assistPackage) {
Chihhang Chuangf264cfb2018-06-05 15:29:06 +0800118 List<ResolveInfo> infos = null;
119
120 if (!TextUtils.isEmpty(assistPackage)) {
yuanjiahsubc20ba82018-11-26 22:57:18 +0800121 Intent queryIntent = new Intent(getIntentAction(context))
Chihhang Chuangf264cfb2018-06-05 15:29:06 +0800122 .setPackage(assistPackage);
123 infos = context.getPackageManager().queryIntentActivities(queryIntent, 0);
124 }
125 return infos;
126 }
127
128 private static boolean isSystemApp(PackageInfo info) {
129 return info.applicationInfo != null
130 && (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
131 }
Hongming Jin862ce042019-02-05 15:42:50 -0800132
133 private static String getDefaultEmergencyPackage(Context context) {
134 long identity = Binder.clearCallingIdentity();
135 try {
136 return CollectionUtils.firstOrNull(context.getSystemService(RoleManager.class)
137 .getRoleHolders(RoleManager.ROLE_EMERGENCY));
138 } finally {
139 Binder.restoreCallingIdentity(identity);
140 }
141 }
142
143 private static boolean setDefaultEmergencyPackageAsync(Context context, String pkgName) {
144 long identity = Binder.clearCallingIdentity();
145 try {
146 context.getSystemService(RoleManager.class).addRoleHolderAsUser(
147 RoleManager.ROLE_EMERGENCY, pkgName, 0, Process.myUserHandle(),
148 AsyncTask.THREAD_POOL_EXECUTOR, new RoleManagerCallback() {
149 @Override
150 public void onSuccess() {
151 }
152 @Override
153 public void onFailure() {
154 Log.e(TAG, "Failed to set emergency default app.");
155 }
156 });
157 } finally {
158 Binder.restoreCallingIdentity(identity);
159 }
160 return true;
161 }
Chihhang Chuangf264cfb2018-06-05 15:29:06 +0800162}