1/* 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 28import java.util.HashMap; 29 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 71 private final HashMap<Connection, RawGatewayInfo> mMap = Maps.newHashMap(); 72 73 public CallGatewayManager() { 74 } 75 76 /** 77 * Static method returns an object containing the gateway data stored in the extras of the 78 * Intent parameter. If no such data exists, returns a Null-Object RawGatewayInfo. 79 * @param intent The intent from which to read gateway data. 80 * @return A populated or empty RawGatewayInfo object. 81 */ 82 public static RawGatewayInfo getRawGatewayInfo(Intent intent, String number) { 83 if (hasPhoneProviderExtras(intent)) { 84 return new RawGatewayInfo(intent.getStringExtra(EXTRA_GATEWAY_PROVIDER_PACKAGE), 85 getProviderGatewayUri(intent), number); 86 } 87 return EMPTY_INFO; 88 } 89 90 /** 91 * This function sets the current mapping from connection to gatewayInfo so that CallModeler 92 * can request this data when creating Call objects. 93 * @param connection The connection object for the placed outgoing call. 94 * @param gatewayInfo Gateway info gathered using getRawGatewayInfo. 95 */ 96 public void setGatewayInfoForConnection(Connection connection, RawGatewayInfo gatewayInfo) { 97 if (!gatewayInfo.isEmpty()) { 98 mMap.put(connection, gatewayInfo); 99 } else { 100 mMap.remove(connection); 101 } 102 } 103 104 /** 105 * Clears the gateway information previously stored via setGatewayInfoForConnection. 106 */ 107 public void clearGatewayData(Connection connection) { 108 setGatewayInfoForConnection(connection, EMPTY_INFO); 109 } 110 111 /** 112 * If the parameter matches the connection object we previously saved through 113 * setGatewayInfoForConnection, return the associated raw gateway info data. If not, then 114 * return an empty raw gateway info. 115 */ 116 public RawGatewayInfo getGatewayInfo(Connection connection) { 117 final RawGatewayInfo info = mMap.get(connection); 118 if (info != null) { 119 return info; 120 } 121 122 return EMPTY_INFO; 123 } 124 125 /** 126 * Check if all the provider's info is present in the intent. 127 * @param intent Expected to have the provider's extra. 128 * @return true if the intent has all the extras to build the 129 * in-call screen's provider info overlay. 130 */ 131 public static boolean hasPhoneProviderExtras(Intent intent) { 132 if (null == intent) { 133 return false; 134 } 135 final String name = intent.getStringExtra(EXTRA_GATEWAY_PROVIDER_PACKAGE); 136 final String gatewayUri = intent.getStringExtra(EXTRA_GATEWAY_URI); 137 138 return !TextUtils.isEmpty(name) && !TextUtils.isEmpty(gatewayUri); 139 } 140 141 /** 142 * Copy all the expected extras set when a 3rd party provider is 143 * used from the source intent to the destination one. Checks all 144 * the required extras are present, if any is missing, none will 145 * be copied. 146 * @param src Intent which may contain the provider's extras. 147 * @param dst Intent where a copy of the extras will be added if applicable. 148 */ 149 public static void checkAndCopyPhoneProviderExtras(Intent src, Intent dst) { 150 if (!hasPhoneProviderExtras(src)) { 151 Log.d(LOG_TAG, "checkAndCopyPhoneProviderExtras: some or all extras are missing."); 152 return; 153 } 154 155 dst.putExtra(EXTRA_GATEWAY_PROVIDER_PACKAGE, 156 src.getStringExtra(EXTRA_GATEWAY_PROVIDER_PACKAGE)); 157 dst.putExtra(EXTRA_GATEWAY_URI, 158 src.getStringExtra(EXTRA_GATEWAY_URI)); 159 } 160 161 /** 162 * Return the gateway uri from the intent. 163 * @param intent With the gateway uri extra. 164 * @return The gateway URI or null if not found. 165 */ 166 public static Uri getProviderGatewayUri(Intent intent) { 167 final String uri = intent.getStringExtra(EXTRA_GATEWAY_URI); 168 return TextUtils.isEmpty(uri) ? null : Uri.parse(uri); 169 } 170 171 /** 172 * Return a formatted version of the uri's scheme specific 173 * part. E.g for 'tel:12345678', return '1-234-5678'. 174 * @param uri A 'tel:' URI with the gateway phone number. 175 * @return the provider's address (from the gateway uri) formatted 176 * for user display. null if uri was null or its scheme was not 'tel:'. 177 */ 178 public static String formatProviderUri(Uri uri) { 179 if (uri != null) { 180 if (Constants.SCHEME_TEL.equals(uri.getScheme())) { 181 return PhoneNumberUtils.formatNumber(uri.getSchemeSpecificPart()); 182 } else { 183 return uri.toString(); 184 } 185 } 186 return null; 187 } 188 189 public static class RawGatewayInfo { 190 public String packageName; 191 public Uri gatewayUri; 192 public String trueNumber; 193 194 public RawGatewayInfo(String packageName, Uri gatewayUri, 195 String trueNumber) { 196 this.packageName = packageName; 197 this.gatewayUri = gatewayUri; 198 this.trueNumber = trueNumber; 199 } 200 201 public String getFormattedGatewayNumber() { 202 return formatProviderUri(gatewayUri); 203 } 204 205 public boolean isEmpty() { 206 return TextUtils.isEmpty(packageName) || gatewayUri == null; 207 } 208 } 209} 210