1c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen/*
2c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen * Copyright (C) 2014 The Android Open Source Project
3c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen *
4c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen * Licensed under the Apache License, Version 2.0 (the "License");
5c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen * you may not use this file except in compliance with the License.
6c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen * You may obtain a copy of the License at
7c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen *
8c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen *      http://www.apache.org/licenses/LICENSE-2.0
9c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen *
10c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen * Unless required by applicable law or agreed to in writing, software
11c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen * distributed under the License is distributed on an "AS IS" BASIS,
12c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen * See the License for the specific language governing permissions and
14c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen * limitations under the License.
15c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen */
16c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen
17c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wenpackage com.android.mms.service;
18c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen
19c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wenimport android.content.Context;
20c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wenimport android.net.ConnectivityManager;
21c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wenimport android.net.Network;
22c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wenimport android.net.NetworkCapabilities;
23c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wenimport android.net.NetworkRequest;
24068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hillimport android.net.NetworkInfo;
25c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wenimport android.os.SystemClock;
262eca933b79d40eb677e878eebb3433dcf2f9db72Ye Wenimport android.provider.Settings;
27c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wenimport android.util.Log;
28c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen
29bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wenimport com.android.mms.service.exception.MmsNetworkException;
30bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wenimport com.android.okhttp.ConnectionPool;
31bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wenimport com.android.okhttp.HostResolver;
32bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen
33b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wenimport java.net.InetAddress;
34b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wenimport java.net.UnknownHostException;
35b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen
36c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen/**
37c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen * Manages the MMS network connectivity
38c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen */
39bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wenpublic class MmsNetworkManager implements HostResolver {
40c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    // Timeout used to call ConnectivityManager.requestNetwork
412eca933b79d40eb677e878eebb3433dcf2f9db72Ye Wen    private static final int NETWORK_REQUEST_TIMEOUT_MILLIS = 60 * 1000;
42c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    // Wait timeout for this class, a little bit longer than the above timeout
43c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    // to make sure we don't bail prematurely
44c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    private static final int NETWORK_ACQUIRE_TIMEOUT_MILLIS =
452eca933b79d40eb677e878eebb3433dcf2f9db72Ye Wen            NETWORK_REQUEST_TIMEOUT_MILLIS + (5 * 1000);
46c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen
47bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen    // Borrowed from {@link android.net.Network}
48bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen    private static final boolean httpKeepAlive =
49bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen            Boolean.parseBoolean(System.getProperty("http.keepAlive", "true"));
50bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen    private static final int httpMaxConnections =
51bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen            httpKeepAlive ? Integer.parseInt(System.getProperty("http.maxConnections", "5")) : 0;
52bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen    private static final long httpKeepAliveDurationMs =
53bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen            Long.parseLong(System.getProperty("http.keepAliveDuration", "300000"));  // 5 minutes.
54bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen
553cf9a9481b8e95d0fb654d083b06ee9a23a8e4e8Ye Wen    private final Context mContext;
563cf9a9481b8e95d0fb654d083b06ee9a23a8e4e8Ye Wen
57c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    // The requested MMS {@link android.net.Network} we are holding
58c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    // We need this when we unbind from it. This is also used to indicate if the
59c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    // MMS network is available.
60c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    private Network mNetwork;
61c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    // The current count of MMS requests that require the MMS network
62c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    // If mMmsRequestCount is 0, we should release the MMS network.
63c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    private int mMmsRequestCount;
640e6456d1c034d76bafeee5877327d32753eab13fYe Wen    // This is really just for using the capability
653cf9a9481b8e95d0fb654d083b06ee9a23a8e4e8Ye Wen    private final NetworkRequest mNetworkRequest;
660e6456d1c034d76bafeee5877327d32753eab13fYe Wen    // The callback to register when we request MMS network
670e6456d1c034d76bafeee5877327d32753eab13fYe Wen    private ConnectivityManager.NetworkCallback mNetworkCallback;
68c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen
69bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen    private volatile ConnectivityManager mConnectivityManager;
70bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen
71bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen    // The OkHttp's ConnectionPool used by the HTTP client associated with this network manager
72bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen    private ConnectionPool mConnectionPool;
73bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen
74bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen    // The MMS HTTP client for this network
75bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen    private MmsHttpClient mMmsHttpClient;
762eca933b79d40eb677e878eebb3433dcf2f9db72Ye Wen
773cf9a9481b8e95d0fb654d083b06ee9a23a8e4e8Ye Wen    // The SIM ID which we use to connect
783cf9a9481b8e95d0fb654d083b06ee9a23a8e4e8Ye Wen    private final int mSubId;
793cf9a9481b8e95d0fb654d083b06ee9a23a8e4e8Ye Wen
803cf9a9481b8e95d0fb654d083b06ee9a23a8e4e8Ye Wen    public MmsNetworkManager(Context context, int subId) {
81c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen        mContext = context;
820e6456d1c034d76bafeee5877327d32753eab13fYe Wen        mNetworkCallback = null;
83c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen        mNetwork = null;
84c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen        mMmsRequestCount = 0;
852eca933b79d40eb677e878eebb3433dcf2f9db72Ye Wen        mConnectivityManager = null;
86bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen        mConnectionPool = null;
87bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen        mMmsHttpClient = null;
883cf9a9481b8e95d0fb654d083b06ee9a23a8e4e8Ye Wen        mSubId = subId;
893cf9a9481b8e95d0fb654d083b06ee9a23a8e4e8Ye Wen        mNetworkRequest = new NetworkRequest.Builder()
903cf9a9481b8e95d0fb654d083b06ee9a23a8e4e8Ye Wen                .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
913cf9a9481b8e95d0fb654d083b06ee9a23a8e4e8Ye Wen                .addCapability(NetworkCapabilities.NET_CAPABILITY_MMS)
923cf9a9481b8e95d0fb654d083b06ee9a23a8e4e8Ye Wen                .setNetworkSpecifier(Integer.toString(mSubId))
933cf9a9481b8e95d0fb654d083b06ee9a23a8e4e8Ye Wen                .build();
94b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen    }
95b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen
96c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    /**
97c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen     * Acquire the MMS network
98c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen     *
99c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen     * @throws com.android.mms.service.exception.MmsNetworkException if we fail to acquire it
100c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen     */
101c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    public void acquireNetwork() throws MmsNetworkException {
102c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen        synchronized (this) {
103c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen            mMmsRequestCount += 1;
104c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen            if (mNetwork != null) {
105c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen                // Already available
106c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen                Log.d(MmsService.TAG, "MmsNetworkManager: already available");
107c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen                return;
108c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen            }
109c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen            Log.d(MmsService.TAG, "MmsNetworkManager: start new network request");
110c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen            // Not available, so start a new request
111c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen            newRequest();
112c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen            final long shouldEnd = SystemClock.elapsedRealtime() + NETWORK_ACQUIRE_TIMEOUT_MILLIS;
113c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen            long waitTime = NETWORK_ACQUIRE_TIMEOUT_MILLIS;
114c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen            while (waitTime > 0) {
115c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen                try {
116c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen                    this.wait(waitTime);
117c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen                } catch (InterruptedException e) {
118c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen                    Log.w(MmsService.TAG, "MmsNetworkManager: acquire network wait interrupted");
119c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen                }
120c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen                if (mNetwork != null) {
121c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen                    // Success
122c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen                    return;
123c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen                }
124c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen                // Calculate remaining waiting time to make sure we wait the full timeout period
125c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen                waitTime = shouldEnd - SystemClock.elapsedRealtime();
126c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen            }
127c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen            // Timed out, so release the request and fail
128c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen            Log.d(MmsService.TAG, "MmsNetworkManager: timed out");
129f3debb19850814e9a857cd45f55cf48cf30f51e0Ye Wen            releaseRequestLocked(mNetworkCallback);
130c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen            throw new MmsNetworkException("Acquiring network timed out");
131c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen        }
132c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    }
133c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen
134c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    /**
135c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen     * Release the MMS network when nobody is holding on to it.
136c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen     */
137c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    public void releaseNetwork() {
138c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen        synchronized (this) {
1390e6456d1c034d76bafeee5877327d32753eab13fYe Wen            if (mMmsRequestCount > 0) {
1400e6456d1c034d76bafeee5877327d32753eab13fYe Wen                mMmsRequestCount -= 1;
1410e6456d1c034d76bafeee5877327d32753eab13fYe Wen                Log.d(MmsService.TAG, "MmsNetworkManager: release, count=" + mMmsRequestCount);
1420e6456d1c034d76bafeee5877327d32753eab13fYe Wen                if (mMmsRequestCount < 1) {
143f3debb19850814e9a857cd45f55cf48cf30f51e0Ye Wen                    releaseRequestLocked(mNetworkCallback);
144c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen                }
145c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen            }
146c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen        }
147c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    }
148c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen
149c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    /**
150c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen     * Start a new {@link android.net.NetworkRequest} for MMS
151c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen     */
152c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    private void newRequest() {
1532eca933b79d40eb677e878eebb3433dcf2f9db72Ye Wen        final ConnectivityManager connectivityManager = getConnectivityManager();
1540e6456d1c034d76bafeee5877327d32753eab13fYe Wen        mNetworkCallback = new ConnectivityManager.NetworkCallback() {
1550e6456d1c034d76bafeee5877327d32753eab13fYe Wen            @Override
1560e6456d1c034d76bafeee5877327d32753eab13fYe Wen            public void onAvailable(Network network) {
1570e6456d1c034d76bafeee5877327d32753eab13fYe Wen                super.onAvailable(network);
1580e6456d1c034d76bafeee5877327d32753eab13fYe Wen                Log.d(MmsService.TAG, "NetworkCallbackListener.onAvailable: network=" + network);
1590e6456d1c034d76bafeee5877327d32753eab13fYe Wen                synchronized (MmsNetworkManager.this) {
1600e6456d1c034d76bafeee5877327d32753eab13fYe Wen                    mNetwork = network;
1610e6456d1c034d76bafeee5877327d32753eab13fYe Wen                    MmsNetworkManager.this.notifyAll();
1620e6456d1c034d76bafeee5877327d32753eab13fYe Wen                }
1630e6456d1c034d76bafeee5877327d32753eab13fYe Wen            }
1640e6456d1c034d76bafeee5877327d32753eab13fYe Wen
1650e6456d1c034d76bafeee5877327d32753eab13fYe Wen            @Override
1660e6456d1c034d76bafeee5877327d32753eab13fYe Wen            public void onLost(Network network) {
1670e6456d1c034d76bafeee5877327d32753eab13fYe Wen                super.onLost(network);
1680e6456d1c034d76bafeee5877327d32753eab13fYe Wen                Log.d(MmsService.TAG, "NetworkCallbackListener.onLost: network=" + network);
1690e6456d1c034d76bafeee5877327d32753eab13fYe Wen                synchronized (MmsNetworkManager.this) {
170f3debb19850814e9a857cd45f55cf48cf30f51e0Ye Wen                    releaseRequestLocked(this);
1710e6456d1c034d76bafeee5877327d32753eab13fYe Wen                    MmsNetworkManager.this.notifyAll();
1720e6456d1c034d76bafeee5877327d32753eab13fYe Wen                }
1730e6456d1c034d76bafeee5877327d32753eab13fYe Wen            }
1740e6456d1c034d76bafeee5877327d32753eab13fYe Wen
1750e6456d1c034d76bafeee5877327d32753eab13fYe Wen            @Override
1760e6456d1c034d76bafeee5877327d32753eab13fYe Wen            public void onUnavailable() {
1770e6456d1c034d76bafeee5877327d32753eab13fYe Wen                super.onUnavailable();
1780e6456d1c034d76bafeee5877327d32753eab13fYe Wen                Log.d(MmsService.TAG, "NetworkCallbackListener.onUnavailable");
1790e6456d1c034d76bafeee5877327d32753eab13fYe Wen                synchronized (MmsNetworkManager.this) {
180f3debb19850814e9a857cd45f55cf48cf30f51e0Ye Wen                    releaseRequestLocked(this);
1810e6456d1c034d76bafeee5877327d32753eab13fYe Wen                    MmsNetworkManager.this.notifyAll();
1820e6456d1c034d76bafeee5877327d32753eab13fYe Wen                }
1830e6456d1c034d76bafeee5877327d32753eab13fYe Wen            }
1840e6456d1c034d76bafeee5877327d32753eab13fYe Wen        };
1850e6456d1c034d76bafeee5877327d32753eab13fYe Wen        connectivityManager.requestNetwork(
1860e6456d1c034d76bafeee5877327d32753eab13fYe Wen                mNetworkRequest, mNetworkCallback, NETWORK_REQUEST_TIMEOUT_MILLIS);
187c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    }
188c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen
189c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    /**
190c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen     * Release the current {@link android.net.NetworkRequest} for MMS
1910e6456d1c034d76bafeee5877327d32753eab13fYe Wen     *
1920e6456d1c034d76bafeee5877327d32753eab13fYe Wen     * @param callback the {@link android.net.ConnectivityManager.NetworkCallback} to unregister
1930e6456d1c034d76bafeee5877327d32753eab13fYe Wen     */
194f3debb19850814e9a857cd45f55cf48cf30f51e0Ye Wen    private void releaseRequestLocked(ConnectivityManager.NetworkCallback callback) {
1950e6456d1c034d76bafeee5877327d32753eab13fYe Wen        if (callback != null) {
1962eca933b79d40eb677e878eebb3433dcf2f9db72Ye Wen            final ConnectivityManager connectivityManager = getConnectivityManager();
1970e6456d1c034d76bafeee5877327d32753eab13fYe Wen            connectivityManager.unregisterNetworkCallback(callback);
1980e6456d1c034d76bafeee5877327d32753eab13fYe Wen        }
199f3debb19850814e9a857cd45f55cf48cf30f51e0Ye Wen        resetLocked();
2000e6456d1c034d76bafeee5877327d32753eab13fYe Wen    }
2010e6456d1c034d76bafeee5877327d32753eab13fYe Wen
2020e6456d1c034d76bafeee5877327d32753eab13fYe Wen    /**
2030e6456d1c034d76bafeee5877327d32753eab13fYe Wen     * Reset the state
204c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen     */
205db7f2fadc52aeaad26450d3a59c1dc9df539780cYe Wen    private void resetLocked() {
2060e6456d1c034d76bafeee5877327d32753eab13fYe Wen        mNetworkCallback = null;
2070e6456d1c034d76bafeee5877327d32753eab13fYe Wen        mNetwork = null;
2080e6456d1c034d76bafeee5877327d32753eab13fYe Wen        mMmsRequestCount = 0;
209bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen        // Currently we follow what android.net.Network does with ConnectionPool,
210bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen        // which is per Network object. So if Network changes, we should clear
211bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen        // out the ConnectionPool and thus the MmsHttpClient (since it is linked
212bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen        // to a specific ConnectionPool).
213bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen        mConnectionPool = null;
214bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen        mMmsHttpClient = null;
215c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    }
216b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen
217f3debb19850814e9a857cd45f55cf48cf30f51e0Ye Wen    private static final InetAddress[] EMPTY_ADDRESS_ARRAY = new InetAddress[0];
218b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen    @Override
219b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen    public InetAddress[] getAllByName(String host) throws UnknownHostException {
220f3debb19850814e9a857cd45f55cf48cf30f51e0Ye Wen        Network network = null;
221db7f2fadc52aeaad26450d3a59c1dc9df539780cYe Wen        synchronized (this) {
222f3debb19850814e9a857cd45f55cf48cf30f51e0Ye Wen            if (mNetwork == null) {
223f3debb19850814e9a857cd45f55cf48cf30f51e0Ye Wen                return EMPTY_ADDRESS_ARRAY;
224db7f2fadc52aeaad26450d3a59c1dc9df539780cYe Wen            }
225f3debb19850814e9a857cd45f55cf48cf30f51e0Ye Wen            network = mNetwork;
226b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen        }
227f3debb19850814e9a857cd45f55cf48cf30f51e0Ye Wen        return network.getAllByName(host);
228b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen    }
2292eca933b79d40eb677e878eebb3433dcf2f9db72Ye Wen
2302eca933b79d40eb677e878eebb3433dcf2f9db72Ye Wen    private ConnectivityManager getConnectivityManager() {
2312eca933b79d40eb677e878eebb3433dcf2f9db72Ye Wen        if (mConnectivityManager == null) {
2322eca933b79d40eb677e878eebb3433dcf2f9db72Ye Wen            mConnectivityManager = (ConnectivityManager) mContext.getSystemService(
2332eca933b79d40eb677e878eebb3433dcf2f9db72Ye Wen                    Context.CONNECTIVITY_SERVICE);
2342eca933b79d40eb677e878eebb3433dcf2f9db72Ye Wen        }
2352eca933b79d40eb677e878eebb3433dcf2f9db72Ye Wen        return mConnectivityManager;
2362eca933b79d40eb677e878eebb3433dcf2f9db72Ye Wen    }
2372eca933b79d40eb677e878eebb3433dcf2f9db72Ye Wen
238bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen    private ConnectionPool getOrCreateConnectionPoolLocked() {
239bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen        if (mConnectionPool == null) {
240bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen            mConnectionPool = new ConnectionPool(httpMaxConnections, httpKeepAliveDurationMs);
241bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen        }
242bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen        return mConnectionPool;
243bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen    }
244bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen
245bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen    /**
246bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen     * Get an MmsHttpClient for the current network
247bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen     *
248bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen     * @return The MmsHttpClient instance
249bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen     */
250bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen    public MmsHttpClient getOrCreateHttpClient() {
251bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen        synchronized (this) {
252bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen            if (mMmsHttpClient == null) {
253bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen                if (mNetwork != null) {
254bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen                    // Create new MmsHttpClient for the current Network
255bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen                    mMmsHttpClient = new MmsHttpClient(
256bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen                            mContext,
257bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen                            mNetwork.getSocketFactory(),
258bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen                            MmsNetworkManager.this,
259bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen                            getOrCreateConnectionPoolLocked());
260bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen                }
261bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen            }
262bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen            return mMmsHttpClient;
263bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen        }
264bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen    }
265068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill
266068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill    /**
267068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill     * Get the APN name for the active network
268068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill     *
269068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill     * @return The APN name if available, otherwise null
270068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill     */
271068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill    public String getApnName() {
272068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill        Network network = null;
273068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill        synchronized (this) {
274068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill            if (mNetwork == null) {
275068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill                Log.d(MmsService.TAG, "MmsNetworkManager: getApnName: network not available");
276068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill                return null;
277068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill            }
278068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill            network = mNetwork;
279068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill        }
280068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill        String apnName = null;
281068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill        final ConnectivityManager connectivityManager = getConnectivityManager();
282068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill        NetworkInfo mmsNetworkInfo = connectivityManager.getNetworkInfo(network);
283068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill        if (mmsNetworkInfo != null) {
284068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill            apnName = mmsNetworkInfo.getExtraInfo();
285068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill        }
286068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill        Log.d(MmsService.TAG, "MmsNetworkManager: getApnName: " + apnName);
287068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill        return apnName;
288068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill    }
289c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen}
290