blob: a349d1721862af951912a4fd6bbb5a745dba6b5a [file] [log] [blame]
Santos Cordon69a69192013-08-22 14:25:42 -07001/*
2 * Copyright (C) 2013 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
19import android.content.Intent;
20import android.net.Uri;
Jay Shrauner137458b2014-09-05 14:27:25 -070021import android.telecomm.PhoneAccount;
Santos Cordon69a69192013-08-22 14:25:42 -070022import android.telephony.PhoneNumberUtils;
23import android.text.TextUtils;
24import android.util.Log;
25
26import com.android.internal.telephony.Connection;
27import com.google.android.collect.Maps;
28
Jay Shrauner21a75342013-11-25 16:14:43 -080029import java.util.concurrent.ConcurrentHashMap;
Santos Cordon69a69192013-08-22 14:25:42 -070030
31/**
32 * This class manages gateway information for outgoing calls. When calls are made, they may contain
33 * gateway information for services which route phone calls through their own service/numbers.
34 * The data consists of a number to call and the package name of the service. This data is used in
35 * two ways:<br/>
36 * 1. Call the appropriate routing number<br/>
37 * 2. Display information about the routing to the user<br/>
38 *
39 * <p>When an outgoing call is finally placed in PhoneUtils.placeCall, it uses this class to get the
40 * proper number to dial. It also saves an association between the connection object and the gateway
Sailesh Nepal23d9ed72014-07-03 09:40:26 -070041 * data into this class.
Santos Cordon69a69192013-08-22 14:25:42 -070042 */
43public class CallGatewayManager {
44 private static final String LOG_TAG = CallGatewayManager.class.getSimpleName();
45
46 /**
47 * Intent extra to specify the package name of the gateway
48 * provider. Used to get the name displayed in the in-call screen
49 * during the call setup. The value is a string.
50 */
51 // TODO: This extra is currently set by the gateway application as
52 // a temporary measure. Ultimately, the framework will securely
53 // set it.
54 /* package */ static final String EXTRA_GATEWAY_PROVIDER_PACKAGE =
55 "com.android.phone.extra.GATEWAY_PROVIDER_PACKAGE";
56
57 /**
58 * Intent extra to specify the URI of the provider to place the
59 * call. The value is a string. It holds the gateway address
60 * (phone gateway URL should start with the 'tel:' scheme) that
61 * will actually be contacted to call the number passed in the
62 * intent URL or in the EXTRA_PHONE_NUMBER extra.
63 */
64 // TODO: Should the value be a Uri (Parcelable)? Need to make sure
65 // MMI code '#' don't get confused as URI fragments.
66 /* package */ static final String EXTRA_GATEWAY_URI =
67 "com.android.phone.extra.GATEWAY_URI";
68
69 public static final RawGatewayInfo EMPTY_INFO = new RawGatewayInfo(null, null, null);
70
Jay Shrauner21a75342013-11-25 16:14:43 -080071 private final ConcurrentHashMap<Connection, RawGatewayInfo> mMap =
72 new ConcurrentHashMap<Connection, RawGatewayInfo>(4, 0.9f, 1);
Santos Cordon69a69192013-08-22 14:25:42 -070073
Jay Shrauner21a75342013-11-25 16:14:43 -080074 private static CallGatewayManager sSingleton;
75
76 public static synchronized CallGatewayManager getInstance() {
77 if (sSingleton == null) {
78 sSingleton = new CallGatewayManager();
79 }
80 return sSingleton;
81 }
82
83 private CallGatewayManager() {
Santos Cordon69a69192013-08-22 14:25:42 -070084 }
85
86 /**
87 * Static method returns an object containing the gateway data stored in the extras of the
88 * Intent parameter. If no such data exists, returns a Null-Object RawGatewayInfo.
89 * @param intent The intent from which to read gateway data.
90 * @return A populated or empty RawGatewayInfo object.
91 */
92 public static RawGatewayInfo getRawGatewayInfo(Intent intent, String number) {
93 if (hasPhoneProviderExtras(intent)) {
94 return new RawGatewayInfo(intent.getStringExtra(EXTRA_GATEWAY_PROVIDER_PACKAGE),
95 getProviderGatewayUri(intent), number);
96 }
97 return EMPTY_INFO;
98 }
99
100 /**
Sailesh Nepal23d9ed72014-07-03 09:40:26 -0700101 * This function sets the current mapping from connection to gatewayInfo.
Santos Cordon69a69192013-08-22 14:25:42 -0700102 * @param connection The connection object for the placed outgoing call.
103 * @param gatewayInfo Gateway info gathered using getRawGatewayInfo.
104 */
105 public void setGatewayInfoForConnection(Connection connection, RawGatewayInfo gatewayInfo) {
106 if (!gatewayInfo.isEmpty()) {
107 mMap.put(connection, gatewayInfo);
108 } else {
109 mMap.remove(connection);
110 }
111 }
112
113 /**
114 * Clears the gateway information previously stored via setGatewayInfoForConnection.
115 */
116 public void clearGatewayData(Connection connection) {
117 setGatewayInfoForConnection(connection, EMPTY_INFO);
118 }
119
120 /**
121 * If the parameter matches the connection object we previously saved through
122 * setGatewayInfoForConnection, return the associated raw gateway info data. If not, then
123 * return an empty raw gateway info.
124 */
125 public RawGatewayInfo getGatewayInfo(Connection connection) {
126 final RawGatewayInfo info = mMap.get(connection);
127 if (info != null) {
128 return info;
129 }
130
131 return EMPTY_INFO;
132 }
133
134 /**
135 * Check if all the provider's info is present in the intent.
136 * @param intent Expected to have the provider's extra.
137 * @return true if the intent has all the extras to build the
138 * in-call screen's provider info overlay.
139 */
140 public static boolean hasPhoneProviderExtras(Intent intent) {
141 if (null == intent) {
142 return false;
143 }
144 final String name = intent.getStringExtra(EXTRA_GATEWAY_PROVIDER_PACKAGE);
145 final String gatewayUri = intent.getStringExtra(EXTRA_GATEWAY_URI);
146
147 return !TextUtils.isEmpty(name) && !TextUtils.isEmpty(gatewayUri);
148 }
149
150 /**
151 * Copy all the expected extras set when a 3rd party provider is
152 * used from the source intent to the destination one. Checks all
153 * the required extras are present, if any is missing, none will
154 * be copied.
155 * @param src Intent which may contain the provider's extras.
156 * @param dst Intent where a copy of the extras will be added if applicable.
157 */
158 public static void checkAndCopyPhoneProviderExtras(Intent src, Intent dst) {
159 if (!hasPhoneProviderExtras(src)) {
160 Log.d(LOG_TAG, "checkAndCopyPhoneProviderExtras: some or all extras are missing.");
161 return;
162 }
163
164 dst.putExtra(EXTRA_GATEWAY_PROVIDER_PACKAGE,
165 src.getStringExtra(EXTRA_GATEWAY_PROVIDER_PACKAGE));
166 dst.putExtra(EXTRA_GATEWAY_URI,
167 src.getStringExtra(EXTRA_GATEWAY_URI));
168 }
169
170 /**
171 * Return the gateway uri from the intent.
172 * @param intent With the gateway uri extra.
173 * @return The gateway URI or null if not found.
174 */
175 public static Uri getProviderGatewayUri(Intent intent) {
176 final String uri = intent.getStringExtra(EXTRA_GATEWAY_URI);
177 return TextUtils.isEmpty(uri) ? null : Uri.parse(uri);
178 }
179
180 /**
181 * Return a formatted version of the uri's scheme specific
182 * part. E.g for 'tel:12345678', return '1-234-5678'.
183 * @param uri A 'tel:' URI with the gateway phone number.
184 * @return the provider's address (from the gateway uri) formatted
185 * for user display. null if uri was null or its scheme was not 'tel:'.
186 */
187 public static String formatProviderUri(Uri uri) {
188 if (uri != null) {
Jay Shrauner137458b2014-09-05 14:27:25 -0700189 if (PhoneAccount.SCHEME_TEL.equals(uri.getScheme())) {
Santos Cordon69a69192013-08-22 14:25:42 -0700190 return PhoneNumberUtils.formatNumber(uri.getSchemeSpecificPart());
191 } else {
192 return uri.toString();
193 }
194 }
195 return null;
196 }
197
198 public static class RawGatewayInfo {
199 public String packageName;
200 public Uri gatewayUri;
201 public String trueNumber;
202
203 public RawGatewayInfo(String packageName, Uri gatewayUri,
204 String trueNumber) {
205 this.packageName = packageName;
206 this.gatewayUri = gatewayUri;
207 this.trueNumber = trueNumber;
208 }
209
210 public String getFormattedGatewayNumber() {
211 return formatProviderUri(gatewayUri);
212 }
213
214 public boolean isEmpty() {
215 return TextUtils.isEmpty(packageName) || gatewayUri == null;
216 }
217 }
218}