169a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon/*
269a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon * Copyright (C) 2013 The Android Open Source Project
369a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon *
469a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon * Licensed under the Apache License, Version 2.0 (the "License");
569a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon * you may not use this file except in compliance with the License.
669a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon * You may obtain a copy of the License at
769a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon *
869a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon *      http://www.apache.org/licenses/LICENSE-2.0
969a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon *
1069a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon * Unless required by applicable law or agreed to in writing, software
1169a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon * distributed under the License is distributed on an "AS IS" BASIS,
1269a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1369a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon * See the License for the specific language governing permissions and
1469a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon * limitations under the License.
1569a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon */
1669a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon
1769a691914e9b013a7ff52c129d8466c152ed7239Santos Cordonpackage com.android.phone;
1869a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon
1969a691914e9b013a7ff52c129d8466c152ed7239Santos Cordonimport android.content.Intent;
2069a691914e9b013a7ff52c129d8466c152ed7239Santos Cordonimport android.net.Uri;
214d45d1cf58a2003378fd35912d6d73a00001bf06Tyler Gunnimport android.telecom.PhoneAccount;
2269a691914e9b013a7ff52c129d8466c152ed7239Santos Cordonimport android.telephony.PhoneNumberUtils;
2369a691914e9b013a7ff52c129d8466c152ed7239Santos Cordonimport android.text.TextUtils;
2469a691914e9b013a7ff52c129d8466c152ed7239Santos Cordonimport android.util.Log;
2569a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon
2669a691914e9b013a7ff52c129d8466c152ed7239Santos Cordonimport com.android.internal.telephony.Connection;
2769a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon
2821a7534fa69c1cc10809ae33fa0bfa84c5ac1309Jay Shraunerimport java.util.concurrent.ConcurrentHashMap;
2969a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon
3069a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon/**
3169a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon * This class manages gateway information for outgoing calls. When calls are made, they may contain
3269a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon * gateway information for services which route phone calls through their own service/numbers.
3369a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon * The data consists of a number to call and the package name of the service. This data is used in
3469a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon * two ways:<br/>
3569a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon * 1. Call the appropriate routing number<br/>
3669a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon * 2. Display information about the routing to the user<br/>
3769a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon *
3869a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon * <p>When an outgoing call is finally placed in PhoneUtils.placeCall, it uses this class to get the
3969a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon * proper number to dial. It also saves an association between the connection object and the gateway
4023d9ed758fbe78e4afd4067e6845bcaf3387bca7Sailesh Nepal * data into this class.
4169a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon */
4269a691914e9b013a7ff52c129d8466c152ed7239Santos Cordonpublic class CallGatewayManager {
4369a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    private static final String LOG_TAG = CallGatewayManager.class.getSimpleName();
4469a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon
4569a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    /**
4669a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * Intent extra to specify the package name of the gateway
4769a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * provider.  Used to get the name displayed in the in-call screen
4869a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * during the call setup. The value is a string.
4969a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     */
5069a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    // TODO: This extra is currently set by the gateway application as
5169a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    // a temporary measure. Ultimately, the framework will securely
5269a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    // set it.
5369a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    /* package */ static final String EXTRA_GATEWAY_PROVIDER_PACKAGE =
5469a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon            "com.android.phone.extra.GATEWAY_PROVIDER_PACKAGE";
5569a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon
5669a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    /**
5769a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * Intent extra to specify the URI of the provider to place the
5869a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * call. The value is a string. It holds the gateway address
5969a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * (phone gateway URL should start with the 'tel:' scheme) that
6069a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * will actually be contacted to call the number passed in the
6169a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * intent URL or in the EXTRA_PHONE_NUMBER extra.
6269a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     */
6369a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    // TODO: Should the value be a Uri (Parcelable)? Need to make sure
6469a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    // MMI code '#' don't get confused as URI fragments.
6569a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    /* package */ static final String EXTRA_GATEWAY_URI =
6669a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon            "com.android.phone.extra.GATEWAY_URI";
6769a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon
6869a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    public static final RawGatewayInfo EMPTY_INFO = new RawGatewayInfo(null, null, null);
6969a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon
7021a7534fa69c1cc10809ae33fa0bfa84c5ac1309Jay Shrauner    private final ConcurrentHashMap<Connection, RawGatewayInfo> mMap =
7121a7534fa69c1cc10809ae33fa0bfa84c5ac1309Jay Shrauner        new ConcurrentHashMap<Connection, RawGatewayInfo>(4, 0.9f, 1);
7269a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon
7321a7534fa69c1cc10809ae33fa0bfa84c5ac1309Jay Shrauner    private static CallGatewayManager sSingleton;
7421a7534fa69c1cc10809ae33fa0bfa84c5ac1309Jay Shrauner
7521a7534fa69c1cc10809ae33fa0bfa84c5ac1309Jay Shrauner    public static synchronized CallGatewayManager getInstance() {
7621a7534fa69c1cc10809ae33fa0bfa84c5ac1309Jay Shrauner        if (sSingleton == null) {
7721a7534fa69c1cc10809ae33fa0bfa84c5ac1309Jay Shrauner            sSingleton = new CallGatewayManager();
7821a7534fa69c1cc10809ae33fa0bfa84c5ac1309Jay Shrauner        }
7921a7534fa69c1cc10809ae33fa0bfa84c5ac1309Jay Shrauner        return sSingleton;
8021a7534fa69c1cc10809ae33fa0bfa84c5ac1309Jay Shrauner    }
8121a7534fa69c1cc10809ae33fa0bfa84c5ac1309Jay Shrauner
8221a7534fa69c1cc10809ae33fa0bfa84c5ac1309Jay Shrauner    private CallGatewayManager() {
8369a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    }
8469a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon
8569a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    /**
8669a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * Static method returns an object containing the gateway data stored in the extras of the
8769a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * Intent parameter.  If no such data exists, returns a Null-Object RawGatewayInfo.
8869a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * @param intent The intent from which to read gateway data.
8969a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * @return A populated or empty RawGatewayInfo object.
9069a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     */
9169a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    public static RawGatewayInfo getRawGatewayInfo(Intent intent, String number) {
9269a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        if (hasPhoneProviderExtras(intent)) {
9369a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon            return new RawGatewayInfo(intent.getStringExtra(EXTRA_GATEWAY_PROVIDER_PACKAGE),
9469a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon                    getProviderGatewayUri(intent), number);
9569a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        }
9669a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        return EMPTY_INFO;
9769a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    }
9869a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon
9969a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    /**
10023d9ed758fbe78e4afd4067e6845bcaf3387bca7Sailesh Nepal     * This function sets the current mapping from connection to gatewayInfo.
10169a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * @param connection The connection object for the placed outgoing call.
10269a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * @param gatewayInfo Gateway info gathered using getRawGatewayInfo.
10369a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     */
10469a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    public void setGatewayInfoForConnection(Connection connection, RawGatewayInfo gatewayInfo) {
10569a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        if (!gatewayInfo.isEmpty()) {
10669a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon            mMap.put(connection, gatewayInfo);
10769a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        } else {
10869a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon            mMap.remove(connection);
10969a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        }
11069a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    }
11169a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon
11269a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    /**
11369a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * Clears the gateway information previously stored via setGatewayInfoForConnection.
11469a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     */
11569a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    public void clearGatewayData(Connection connection) {
11669a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        setGatewayInfoForConnection(connection, EMPTY_INFO);
11769a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    }
11869a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon
11969a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    /**
12069a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * If the parameter matches the connection object we previously saved through
12169a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * setGatewayInfoForConnection, return the associated raw gateway info data. If not, then
12269a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * return an empty raw gateway info.
12369a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     */
12469a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    public RawGatewayInfo getGatewayInfo(Connection connection) {
12569a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        final RawGatewayInfo info = mMap.get(connection);
12669a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        if (info != null) {
12769a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon            return info;
12869a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        }
12969a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon
13069a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        return EMPTY_INFO;
13169a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    }
13269a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon
13369a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    /**
13469a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * Check if all the provider's info is present in the intent.
13569a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * @param intent Expected to have the provider's extra.
13669a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * @return true if the intent has all the extras to build the
13769a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * in-call screen's provider info overlay.
13869a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     */
13969a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    public static boolean hasPhoneProviderExtras(Intent intent) {
14069a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        if (null == intent) {
14169a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon            return false;
14269a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        }
14369a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        final String name = intent.getStringExtra(EXTRA_GATEWAY_PROVIDER_PACKAGE);
14469a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        final String gatewayUri = intent.getStringExtra(EXTRA_GATEWAY_URI);
14569a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon
14669a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        return !TextUtils.isEmpty(name) && !TextUtils.isEmpty(gatewayUri);
14769a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    }
14869a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon
14969a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    /**
15069a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * Copy all the expected extras set when a 3rd party provider is
15169a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * used from the source intent to the destination one.  Checks all
15269a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * the required extras are present, if any is missing, none will
15369a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * be copied.
15469a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * @param src Intent which may contain the provider's extras.
15569a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * @param dst Intent where a copy of the extras will be added if applicable.
15669a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     */
15769a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    public static void checkAndCopyPhoneProviderExtras(Intent src, Intent dst) {
15869a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        if (!hasPhoneProviderExtras(src)) {
15969a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon            Log.d(LOG_TAG, "checkAndCopyPhoneProviderExtras: some or all extras are missing.");
16069a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon            return;
16169a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        }
16269a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon
16369a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        dst.putExtra(EXTRA_GATEWAY_PROVIDER_PACKAGE,
16469a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon                     src.getStringExtra(EXTRA_GATEWAY_PROVIDER_PACKAGE));
16569a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        dst.putExtra(EXTRA_GATEWAY_URI,
16669a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon                     src.getStringExtra(EXTRA_GATEWAY_URI));
16769a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    }
16869a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon
16969a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    /**
17069a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * Return the gateway uri from the intent.
17169a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * @param intent With the gateway uri extra.
17269a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * @return The gateway URI or null if not found.
17369a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     */
17469a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    public static Uri getProviderGatewayUri(Intent intent) {
17569a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        final String uri = intent.getStringExtra(EXTRA_GATEWAY_URI);
17669a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        return TextUtils.isEmpty(uri) ? null : Uri.parse(uri);
17769a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    }
17869a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon
17969a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    /**
18069a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * Return a formatted version of the uri's scheme specific
18169a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * part. E.g for 'tel:12345678', return '1-234-5678'.
18269a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * @param uri A 'tel:' URI with the gateway phone number.
18369a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * @return the provider's address (from the gateway uri) formatted
18469a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     * for user display. null if uri was null or its scheme was not 'tel:'.
18569a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon     */
18669a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    public static String formatProviderUri(Uri uri) {
18769a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        if (uri != null) {
188137458b4bf3516941483e59c123c22cbee27ed43Jay Shrauner            if (PhoneAccount.SCHEME_TEL.equals(uri.getScheme())) {
18969a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon                return PhoneNumberUtils.formatNumber(uri.getSchemeSpecificPart());
19069a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon            } else {
19169a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon                return uri.toString();
19269a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon            }
19369a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        }
19469a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        return null;
19569a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    }
19669a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon
19769a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    public static class RawGatewayInfo {
19869a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        public String packageName;
19969a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        public Uri gatewayUri;
20069a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        public String trueNumber;
20169a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon
20269a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        public RawGatewayInfo(String packageName, Uri gatewayUri,
20369a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon                String trueNumber) {
20469a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon            this.packageName = packageName;
20569a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon            this.gatewayUri = gatewayUri;
20669a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon            this.trueNumber = trueNumber;
20769a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        }
20869a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon
20969a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        public String getFormattedGatewayNumber() {
21069a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon            return formatProviderUri(gatewayUri);
21169a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        }
21269a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon
21369a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        public boolean isEmpty() {
21469a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon            return TextUtils.isEmpty(packageName) || gatewayUri == null;
21569a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon        }
21669a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon    }
21769a691914e9b013a7ff52c129d8466c152ed7239Santos Cordon}
218