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;
23068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hillimport android.net.NetworkInfo;
247a284e5b43a12ba9e4fa7786786f059bf924dd78Ye Wenimport android.net.NetworkRequest;
25f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskanimport android.os.Handler;
26f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskanimport android.os.Looper;
27c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wenimport android.os.SystemClock;
28c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen
29bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wenimport com.android.mms.service.exception.MmsNetworkException;
30b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen
31c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen/**
32c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen * Manages the MMS network connectivity
33c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen */
347a284e5b43a12ba9e4fa7786786f059bf924dd78Ye Wenpublic class MmsNetworkManager {
35c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    // Timeout used to call ConnectivityManager.requestNetwork
36d0c5b20403b3924cee67e0e72d745b10b0691eacAndre Furtado    // Given that the telephony layer will retry on failures, this timeout should be high enough.
37d0c5b20403b3924cee67e0e72d745b10b0691eacAndre Furtado    private static final int NETWORK_REQUEST_TIMEOUT_MILLIS = 30 * 60 * 1000;
38c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    // Wait timeout for this class, a little bit longer than the above timeout
39c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    // to make sure we don't bail prematurely
40c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    private static final int NETWORK_ACQUIRE_TIMEOUT_MILLIS =
412eca933b79d40eb677e878eebb3433dcf2f9db72Ye Wen            NETWORK_REQUEST_TIMEOUT_MILLIS + (5 * 1000);
42f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan    // Waiting time used before releasing a network prematurely. This allows the MMS download
43f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan    // acknowledgement messages to be sent using the same network that was used to download the data
44f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan    private static final int NETWORK_RELEASE_TIMEOUT_MILLIS = 5 * 1000;
45c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen
463cf9a9481b8e95d0fb654d083b06ee9a23a8e4e8Ye Wen    private final Context mContext;
473cf9a9481b8e95d0fb654d083b06ee9a23a8e4e8Ye Wen
48c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    // The requested MMS {@link android.net.Network} we are holding
49c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    // We need this when we unbind from it. This is also used to indicate if the
50c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    // MMS network is available.
51c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    private Network mNetwork;
52c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    // The current count of MMS requests that require the MMS network
53c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    // If mMmsRequestCount is 0, we should release the MMS network.
54c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    private int mMmsRequestCount;
550e6456d1c034d76bafeee5877327d32753eab13fYe Wen    // This is really just for using the capability
563cf9a9481b8e95d0fb654d083b06ee9a23a8e4e8Ye Wen    private final NetworkRequest mNetworkRequest;
570e6456d1c034d76bafeee5877327d32753eab13fYe Wen    // The callback to register when we request MMS network
580e6456d1c034d76bafeee5877327d32753eab13fYe Wen    private ConnectivityManager.NetworkCallback mNetworkCallback;
59c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen
60bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen    private volatile ConnectivityManager mConnectivityManager;
61bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen
62bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen    // The MMS HTTP client for this network
63bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen    private MmsHttpClient mMmsHttpClient;
642eca933b79d40eb677e878eebb3433dcf2f9db72Ye Wen
65f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan    // The handler used for delayed release of the network
66f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan    private final Handler mReleaseHandler;
67f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan
68f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan    // The task that does the delayed releasing of the network.
69f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan    private final Runnable mNetworkReleaseTask;
70f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan
713cf9a9481b8e95d0fb654d083b06ee9a23a8e4e8Ye Wen    // The SIM ID which we use to connect
723cf9a9481b8e95d0fb654d083b06ee9a23a8e4e8Ye Wen    private final int mSubId;
733cf9a9481b8e95d0fb654d083b06ee9a23a8e4e8Ye Wen
74428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen    /**
75428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen     * Network callback for our network request
76428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen     */
77428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen    private class NetworkRequestCallback extends ConnectivityManager.NetworkCallback {
78428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen        @Override
79428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen        public void onAvailable(Network network) {
80428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen            super.onAvailable(network);
818153aed48a84305533f26c06a07a51bd358cee41Ye Wen            LogUtil.i("NetworkCallbackListener.onAvailable: network=" + network);
82428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen            synchronized (MmsNetworkManager.this) {
83428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen                mNetwork = network;
84428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen                MmsNetworkManager.this.notifyAll();
85428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen            }
86428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen        }
87428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen
88428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen        @Override
89428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen        public void onLost(Network network) {
90428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen            super.onLost(network);
918153aed48a84305533f26c06a07a51bd358cee41Ye Wen            LogUtil.w("NetworkCallbackListener.onLost: network=" + network);
92428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen            synchronized (MmsNetworkManager.this) {
93428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen                releaseRequestLocked(this);
94428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen                MmsNetworkManager.this.notifyAll();
95428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen            }
96428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen        }
97428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen
98428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen        @Override
99428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen        public void onUnavailable() {
100428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen            super.onUnavailable();
1018153aed48a84305533f26c06a07a51bd358cee41Ye Wen            LogUtil.w("NetworkCallbackListener.onUnavailable");
102428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen            synchronized (MmsNetworkManager.this) {
103428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen                releaseRequestLocked(this);
104428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen                MmsNetworkManager.this.notifyAll();
105428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen            }
106428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen        }
107428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen    }
108428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen
1093cf9a9481b8e95d0fb654d083b06ee9a23a8e4e8Ye Wen    public MmsNetworkManager(Context context, int subId) {
110c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen        mContext = context;
1110e6456d1c034d76bafeee5877327d32753eab13fYe Wen        mNetworkCallback = null;
112c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen        mNetwork = null;
113c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen        mMmsRequestCount = 0;
1142eca933b79d40eb677e878eebb3433dcf2f9db72Ye Wen        mConnectivityManager = null;
115bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen        mMmsHttpClient = null;
1163cf9a9481b8e95d0fb654d083b06ee9a23a8e4e8Ye Wen        mSubId = subId;
117f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan        mReleaseHandler = new Handler(Looper.getMainLooper());
1183cf9a9481b8e95d0fb654d083b06ee9a23a8e4e8Ye Wen        mNetworkRequest = new NetworkRequest.Builder()
1193cf9a9481b8e95d0fb654d083b06ee9a23a8e4e8Ye Wen                .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
1203cf9a9481b8e95d0fb654d083b06ee9a23a8e4e8Ye Wen                .addCapability(NetworkCapabilities.NET_CAPABILITY_MMS)
1213cf9a9481b8e95d0fb654d083b06ee9a23a8e4e8Ye Wen                .setNetworkSpecifier(Integer.toString(mSubId))
1223cf9a9481b8e95d0fb654d083b06ee9a23a8e4e8Ye Wen                .build();
123f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan
124f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan        mNetworkReleaseTask = new Runnable() {
125f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan            @Override
126f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan            public void run() {
127f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan                synchronized (this) {
128f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan                    if (mMmsRequestCount < 1) {
129f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan                        releaseRequestLocked(mNetworkCallback);
130f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan                    }
131f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan                }
132f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan            }
133f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan        };
134b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen    }
135b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen
136c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    /**
137c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen     * Acquire the MMS network
138c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen     *
1398153aed48a84305533f26c06a07a51bd358cee41Ye Wen     * @param requestId request ID for logging
140c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen     * @throws com.android.mms.service.exception.MmsNetworkException if we fail to acquire it
141c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen     */
1428153aed48a84305533f26c06a07a51bd358cee41Ye Wen    public void acquireNetwork(final String requestId) throws MmsNetworkException {
143c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen        synchronized (this) {
144f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan            // Since we are acquiring the network, remove the network release task if exists.
145f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan            mReleaseHandler.removeCallbacks(mNetworkReleaseTask);
146c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen            mMmsRequestCount += 1;
147c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen            if (mNetwork != null) {
148c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen                // Already available
1498153aed48a84305533f26c06a07a51bd358cee41Ye Wen                LogUtil.d(requestId, "MmsNetworkManager: already available");
150c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen                return;
151c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen            }
152428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen            // Not available, so start a new request if not done yet
153428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen            if (mNetworkCallback == null) {
1548153aed48a84305533f26c06a07a51bd358cee41Ye Wen                LogUtil.d(requestId, "MmsNetworkManager: start new network request");
155428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen                startNewNetworkRequestLocked();
156428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen            }
157c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen            final long shouldEnd = SystemClock.elapsedRealtime() + NETWORK_ACQUIRE_TIMEOUT_MILLIS;
158c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen            long waitTime = NETWORK_ACQUIRE_TIMEOUT_MILLIS;
159c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen            while (waitTime > 0) {
160c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen                try {
161c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen                    this.wait(waitTime);
162c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen                } catch (InterruptedException e) {
1638153aed48a84305533f26c06a07a51bd358cee41Ye Wen                    LogUtil.w(requestId, "MmsNetworkManager: acquire network wait interrupted");
164c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen                }
165c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen                if (mNetwork != null) {
166c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen                    // Success
167c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen                    return;
168c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen                }
169c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen                // Calculate remaining waiting time to make sure we wait the full timeout period
170c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen                waitTime = shouldEnd - SystemClock.elapsedRealtime();
171c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen            }
172c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen            // Timed out, so release the request and fail
1738153aed48a84305533f26c06a07a51bd358cee41Ye Wen            LogUtil.e(requestId, "MmsNetworkManager: timed out");
174f3debb19850814e9a857cd45f55cf48cf30f51e0Ye Wen            releaseRequestLocked(mNetworkCallback);
175c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen            throw new MmsNetworkException("Acquiring network timed out");
176c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen        }
177c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    }
178c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen
179c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    /**
180c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen     * Release the MMS network when nobody is holding on to it.
1818153aed48a84305533f26c06a07a51bd358cee41Ye Wen     *
1828153aed48a84305533f26c06a07a51bd358cee41Ye Wen     * @param requestId request ID for logging
183f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan     * @param shouldDelayRelease whether the release should be delayed for 5 seconds, the regular
184f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan     *                           use case is to delay this for DownloadRequests to use the network
185f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan     *                           for sending an acknowledgement on the same network
186c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen     */
187f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan    public void releaseNetwork(final String requestId, final boolean shouldDelayRelease) {
188c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen        synchronized (this) {
1890e6456d1c034d76bafeee5877327d32753eab13fYe Wen            if (mMmsRequestCount > 0) {
1900e6456d1c034d76bafeee5877327d32753eab13fYe Wen                mMmsRequestCount -= 1;
1918153aed48a84305533f26c06a07a51bd358cee41Ye Wen                LogUtil.d(requestId, "MmsNetworkManager: release, count=" + mMmsRequestCount);
1920e6456d1c034d76bafeee5877327d32753eab13fYe Wen                if (mMmsRequestCount < 1) {
193f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan                    if (shouldDelayRelease) {
194f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan                        // remove previously posted task and post a delayed task on the release
195f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan                        // handler to release the network
196f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan                        mReleaseHandler.removeCallbacks(mNetworkReleaseTask);
197f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan                        mReleaseHandler.postDelayed(mNetworkReleaseTask,
198f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan                                NETWORK_RELEASE_TIMEOUT_MILLIS);
199f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan                    } else {
200f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan                        releaseRequestLocked(mNetworkCallback);
201f37c91b2ad585acf86f843efc275a063615b0f3bSahin Caliskan                    }
202c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen                }
203c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen            }
204c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen        }
205c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    }
206c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen
207c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    /**
208c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen     * Start a new {@link android.net.NetworkRequest} for MMS
209c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen     */
210428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen    private void startNewNetworkRequestLocked() {
2112eca933b79d40eb677e878eebb3433dcf2f9db72Ye Wen        final ConnectivityManager connectivityManager = getConnectivityManager();
212428fa0b017e40c2cd210a4c974e57c5e85584441Ye Wen        mNetworkCallback = new NetworkRequestCallback();
2130e6456d1c034d76bafeee5877327d32753eab13fYe Wen        connectivityManager.requestNetwork(
2140e6456d1c034d76bafeee5877327d32753eab13fYe Wen                mNetworkRequest, mNetworkCallback, NETWORK_REQUEST_TIMEOUT_MILLIS);
215c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    }
216c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen
217c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    /**
218c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen     * Release the current {@link android.net.NetworkRequest} for MMS
2190e6456d1c034d76bafeee5877327d32753eab13fYe Wen     *
2200e6456d1c034d76bafeee5877327d32753eab13fYe Wen     * @param callback the {@link android.net.ConnectivityManager.NetworkCallback} to unregister
2210e6456d1c034d76bafeee5877327d32753eab13fYe Wen     */
222f3debb19850814e9a857cd45f55cf48cf30f51e0Ye Wen    private void releaseRequestLocked(ConnectivityManager.NetworkCallback callback) {
2230e6456d1c034d76bafeee5877327d32753eab13fYe Wen        if (callback != null) {
2242eca933b79d40eb677e878eebb3433dcf2f9db72Ye Wen            final ConnectivityManager connectivityManager = getConnectivityManager();
2257109ffadcf870446f6d606513ac6ca66b2ec83b4Ye Wen            try {
2267109ffadcf870446f6d606513ac6ca66b2ec83b4Ye Wen                connectivityManager.unregisterNetworkCallback(callback);
2277109ffadcf870446f6d606513ac6ca66b2ec83b4Ye Wen            } catch (IllegalArgumentException e) {
2287109ffadcf870446f6d606513ac6ca66b2ec83b4Ye Wen                // It is possible ConnectivityManager.requestNetwork may fail silently due
2297109ffadcf870446f6d606513ac6ca66b2ec83b4Ye Wen                // to RemoteException. When that happens, we may get an invalid
2307109ffadcf870446f6d606513ac6ca66b2ec83b4Ye Wen                // NetworkCallback, which causes an IllegalArgumentexception when we try to
2317109ffadcf870446f6d606513ac6ca66b2ec83b4Ye Wen                // unregisterNetworkCallback. This exception in turn causes
2327109ffadcf870446f6d606513ac6ca66b2ec83b4Ye Wen                // MmsNetworkManager to skip resetLocked() in the below. Thus MMS service
2337109ffadcf870446f6d606513ac6ca66b2ec83b4Ye Wen                // would get stuck in the bad state until the device restarts. This fix
2347109ffadcf870446f6d606513ac6ca66b2ec83b4Ye Wen                // catches the exception so that state clean up can be executed.
2357109ffadcf870446f6d606513ac6ca66b2ec83b4Ye Wen                LogUtil.w("Unregister network callback exception", e);
2367109ffadcf870446f6d606513ac6ca66b2ec83b4Ye Wen            }
2370e6456d1c034d76bafeee5877327d32753eab13fYe Wen        }
238f3debb19850814e9a857cd45f55cf48cf30f51e0Ye Wen        resetLocked();
2390e6456d1c034d76bafeee5877327d32753eab13fYe Wen    }
2400e6456d1c034d76bafeee5877327d32753eab13fYe Wen
2410e6456d1c034d76bafeee5877327d32753eab13fYe Wen    /**
2420e6456d1c034d76bafeee5877327d32753eab13fYe Wen     * Reset the state
243c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen     */
244db7f2fadc52aeaad26450d3a59c1dc9df539780cYe Wen    private void resetLocked() {
2450e6456d1c034d76bafeee5877327d32753eab13fYe Wen        mNetworkCallback = null;
2460e6456d1c034d76bafeee5877327d32753eab13fYe Wen        mNetwork = null;
2470e6456d1c034d76bafeee5877327d32753eab13fYe Wen        mMmsRequestCount = 0;
248bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen        mMmsHttpClient = null;
249c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    }
250b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen
2512eca933b79d40eb677e878eebb3433dcf2f9db72Ye Wen    private ConnectivityManager getConnectivityManager() {
2522eca933b79d40eb677e878eebb3433dcf2f9db72Ye Wen        if (mConnectivityManager == null) {
2532eca933b79d40eb677e878eebb3433dcf2f9db72Ye Wen            mConnectivityManager = (ConnectivityManager) mContext.getSystemService(
2542eca933b79d40eb677e878eebb3433dcf2f9db72Ye Wen                    Context.CONNECTIVITY_SERVICE);
2552eca933b79d40eb677e878eebb3433dcf2f9db72Ye Wen        }
2562eca933b79d40eb677e878eebb3433dcf2f9db72Ye Wen        return mConnectivityManager;
2572eca933b79d40eb677e878eebb3433dcf2f9db72Ye Wen    }
2582eca933b79d40eb677e878eebb3433dcf2f9db72Ye Wen
259bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen    /**
260bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen     * Get an MmsHttpClient for the current network
261bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen     *
262bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen     * @return The MmsHttpClient instance
263bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen     */
264bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen    public MmsHttpClient getOrCreateHttpClient() {
265bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen        synchronized (this) {
266bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen            if (mMmsHttpClient == null) {
267bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen                if (mNetwork != null) {
268bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen                    // Create new MmsHttpClient for the current Network
269eeb364a1e8916609bee877b893443bd940ea87daYe Wen                    mMmsHttpClient = new MmsHttpClient(mContext, mNetwork, mConnectivityManager);
270bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen                }
271bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen            }
272bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen            return mMmsHttpClient;
273bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen        }
274bdb6fe1cfbc8ecb7ed56798f49de7ba62019fd72Ye Wen    }
275068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill
276068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill    /**
277068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill     * Get the APN name for the active network
278068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill     *
279068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill     * @return The APN name if available, otherwise null
280068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill     */
281068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill    public String getApnName() {
282068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill        Network network = null;
283068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill        synchronized (this) {
284068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill            if (mNetwork == null) {
285068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill                return null;
286068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill            }
287068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill            network = mNetwork;
288068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill        }
289068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill        String apnName = null;
290068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill        final ConnectivityManager connectivityManager = getConnectivityManager();
2918153aed48a84305533f26c06a07a51bd358cee41Ye Wen        final NetworkInfo mmsNetworkInfo = connectivityManager.getNetworkInfo(network);
292068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill        if (mmsNetworkInfo != null) {
293068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill            apnName = mmsNetworkInfo.getExtraInfo();
294068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill        }
295068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill        return apnName;
296068f2012ef6f6e58f06bfbe7c88604a176d69657Tony Hill    }
297c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen}
298