blob: 81bee07776215714efb4e2fa8d403daa38bf474f [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;
21import android.telephony.PhoneNumberUtils;
22import android.text.TextUtils;
23import android.util.Log;
24
25import com.android.internal.telephony.Connection;
26import com.google.android.collect.Maps;
27
Jay Shraunerb2bf8522013-11-25 16:14:43 -080028import java.util.concurrent.ConcurrentHashMap;
Santos Cordon69a69192013-08-22 14:25:42 -070029
30/**
31 * This class manages gateway information for outgoing calls. When calls are made, they may contain
32 * gateway information for services which route phone calls through their own service/numbers.
33 * The data consists of a number to call and the package name of the service. This data is used in
34 * two ways:<br/>
35 * 1. Call the appropriate routing number<br/>
36 * 2. Display information about the routing to the user<br/>
37 *
38 * <p>When an outgoing call is finally placed in PhoneUtils.placeCall, it uses this class to get the
39 * proper number to dial. It also saves an association between the connection object and the gateway
40 * data into this class. This association is later used in CallModeler when building Call objects
41 * to send to the UI which require the gateway data to show an alert to users.
42 */
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 Shraunerb2bf8522013-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 Shraunerb2bf8522013-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 /**
101 * This function sets the current mapping from connection to gatewayInfo so that CallModeler
102 * can request this data when creating Call objects.
103 * @param connection The connection object for the placed outgoing call.
104 * @param gatewayInfo Gateway info gathered using getRawGatewayInfo.
105 */
106 public void setGatewayInfoForConnection(Connection connection, RawGatewayInfo gatewayInfo) {
107 if (!gatewayInfo.isEmpty()) {
108 mMap.put(connection, gatewayInfo);
109 } else {
110 mMap.remove(connection);
111 }
112 }
113
114 /**
115 * Clears the gateway information previously stored via setGatewayInfoForConnection.
116 */
117 public void clearGatewayData(Connection connection) {
118 setGatewayInfoForConnection(connection, EMPTY_INFO);
119 }
120
121 /**
122 * If the parameter matches the connection object we previously saved through
123 * setGatewayInfoForConnection, return the associated raw gateway info data. If not, then
124 * return an empty raw gateway info.
125 */
126 public RawGatewayInfo getGatewayInfo(Connection connection) {
127 final RawGatewayInfo info = mMap.get(connection);
128 if (info != null) {
129 return info;
130 }
131
132 return EMPTY_INFO;
133 }
134
135 /**
136 * Check if all the provider's info is present in the intent.
137 * @param intent Expected to have the provider's extra.
138 * @return true if the intent has all the extras to build the
139 * in-call screen's provider info overlay.
140 */
141 public static boolean hasPhoneProviderExtras(Intent intent) {
142 if (null == intent) {
143 return false;
144 }
145 final String name = intent.getStringExtra(EXTRA_GATEWAY_PROVIDER_PACKAGE);
146 final String gatewayUri = intent.getStringExtra(EXTRA_GATEWAY_URI);
147
148 return !TextUtils.isEmpty(name) && !TextUtils.isEmpty(gatewayUri);
149 }
150
151 /**
152 * Copy all the expected extras set when a 3rd party provider is
153 * used from the source intent to the destination one. Checks all
154 * the required extras are present, if any is missing, none will
155 * be copied.
156 * @param src Intent which may contain the provider's extras.
157 * @param dst Intent where a copy of the extras will be added if applicable.
158 */
159 public static void checkAndCopyPhoneProviderExtras(Intent src, Intent dst) {
160 if (!hasPhoneProviderExtras(src)) {
161 Log.d(LOG_TAG, "checkAndCopyPhoneProviderExtras: some or all extras are missing.");
162 return;
163 }
164
165 dst.putExtra(EXTRA_GATEWAY_PROVIDER_PACKAGE,
166 src.getStringExtra(EXTRA_GATEWAY_PROVIDER_PACKAGE));
167 dst.putExtra(EXTRA_GATEWAY_URI,
168 src.getStringExtra(EXTRA_GATEWAY_URI));
169 }
170
171 /**
172 * Return the gateway uri from the intent.
173 * @param intent With the gateway uri extra.
174 * @return The gateway URI or null if not found.
175 */
176 public static Uri getProviderGatewayUri(Intent intent) {
177 final String uri = intent.getStringExtra(EXTRA_GATEWAY_URI);
178 return TextUtils.isEmpty(uri) ? null : Uri.parse(uri);
179 }
180
181 /**
182 * Return a formatted version of the uri's scheme specific
183 * part. E.g for 'tel:12345678', return '1-234-5678'.
184 * @param uri A 'tel:' URI with the gateway phone number.
185 * @return the provider's address (from the gateway uri) formatted
186 * for user display. null if uri was null or its scheme was not 'tel:'.
187 */
188 public static String formatProviderUri(Uri uri) {
189 if (uri != null) {
190 if (Constants.SCHEME_TEL.equals(uri.getScheme())) {
191 return PhoneNumberUtils.formatNumber(uri.getSchemeSpecificPart());
192 } else {
193 return uri.toString();
194 }
195 }
196 return null;
197 }
198
199 public static class RawGatewayInfo {
200 public String packageName;
201 public Uri gatewayUri;
202 public String trueNumber;
203
204 public RawGatewayInfo(String packageName, Uri gatewayUri,
205 String trueNumber) {
206 this.packageName = packageName;
207 this.gatewayUri = gatewayUri;
208 this.trueNumber = trueNumber;
209 }
210
211 public String getFormattedGatewayNumber() {
212 return formatProviderUri(gatewayUri);
213 }
214
215 public boolean isEmpty() {
216 return TextUtils.isEmpty(packageName) || gatewayUri == null;
217 }
218 }
219}