MmsRequest.java revision b2823fa889f5c1bde4047af36b3b07672942f700
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 com.android.mms.service.exception.ApnException;
20c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wenimport com.android.mms.service.exception.MmsHttpException;
21c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wenimport com.android.mms.service.exception.MmsNetworkException;
22c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen
23c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wenimport android.app.Activity;
24c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wenimport android.app.PendingIntent;
25b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wenimport android.content.BroadcastReceiver;
26c984707ecf54d545a4a5809c6ce1d18bf7cee61eYe Wenimport android.content.ContentValues;
27c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wenimport android.content.Context;
28c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wenimport android.content.Intent;
29b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wenimport android.net.ConnectivityManager;
30b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wenimport android.net.LinkProperties;
31b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wenimport android.net.Network;
323a14e46a22e95062102a19c955a819bf239dbc52Ye Wenimport android.net.Uri;
33b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wenimport android.os.Bundle;
34b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wenimport android.provider.Telephony;
354fd5a8951574cb8a74126c41ec890374eb09e8b9Ye Wenimport android.telephony.SmsManager;
36c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wenimport android.util.Log;
37c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen
38b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wenimport java.net.Inet4Address;
39b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wenimport java.net.Inet6Address;
40b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wenimport java.net.InetAddress;
41b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wenimport java.net.UnknownHostException;
42b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wenimport java.util.ArrayList;
43b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wenimport java.util.List;
44b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen
45c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen/**
46c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen * Base class for MMS requests. This has the common logic of sending/downloading MMS.
47c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen */
48c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wenpublic abstract class MmsRequest {
49c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    private static final int RETRY_TIMES = 3;
50c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen
51b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen    protected static final String EXTRA_MESSAGE_REF = "messageref";
52b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen
53b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen    /**
54b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen     * Interface for certain functionalities from MmsService
55b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen     */
56b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen    public static interface RequestManager {
57b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen        /**
58b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen         * Add a request to pending queue when it is executed by carrier app
59b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen         *
60b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen         * @param key The message ref key from carrier app
61b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen         * @param request The request in pending
62b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen         */
63b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen        public void addPending(int key, MmsRequest request);
64b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen
65b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen        /**
66b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen         * Enqueue an MMS request for running
67b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen         *
68b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen         * @param request the request to enqueue
69b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen         */
70b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen        public void addRunning(MmsRequest request);
716f31811156a8aeef55011749c25d7c98d7a7a7ddShishir Agrawal
728c027a60c84d23672647a3775190ee3fa7655b34Ye Wen        /*
738c027a60c84d23672647a3775190ee3fa7655b34Ye Wen         * @return Whether to auto persist received MMS
748c027a60c84d23672647a3775190ee3fa7655b34Ye Wen         */
758c027a60c84d23672647a3775190ee3fa7655b34Ye Wen        public boolean getAutoPersistingPref();
76b83f2faa04dc275b6779644308384459ffcff63fJulian Odell
77b83f2faa04dc275b6779644308384459ffcff63fJulian Odell        /**
78b83f2faa04dc275b6779644308384459ffcff63fJulian Odell         * Read pdu (up to maxSize bytes) from supplied content uri
79b83f2faa04dc275b6779644308384459ffcff63fJulian Odell         * @param contentUri content uri from which to read
80b83f2faa04dc275b6779644308384459ffcff63fJulian Odell         * @param maxSize maximum number of bytes to read
81b83f2faa04dc275b6779644308384459ffcff63fJulian Odell         * @return read pdu (else null in case of error or too big)
82b83f2faa04dc275b6779644308384459ffcff63fJulian Odell         */
83b83f2faa04dc275b6779644308384459ffcff63fJulian Odell        public byte[] readPduFromContentUri(final Uri contentUri, final int maxSize);
84b83f2faa04dc275b6779644308384459ffcff63fJulian Odell
85b83f2faa04dc275b6779644308384459ffcff63fJulian Odell        /**
86b83f2faa04dc275b6779644308384459ffcff63fJulian Odell         * Write pdu to supplied content uri
87b83f2faa04dc275b6779644308384459ffcff63fJulian Odell         * @param contentUri content uri to which bytes should be written
88b83f2faa04dc275b6779644308384459ffcff63fJulian Odell         * @param pdu pdu bytes to write
89b83f2faa04dc275b6779644308384459ffcff63fJulian Odell         * @return true in case of success (else false)
90b83f2faa04dc275b6779644308384459ffcff63fJulian Odell         */
91b83f2faa04dc275b6779644308384459ffcff63fJulian Odell        public boolean writePduToContentUri(final Uri contentUri, final byte[] pdu);
92b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen    }
93b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen
943a14e46a22e95062102a19c955a819bf239dbc52Ye Wen    // The URI of persisted message
953a14e46a22e95062102a19c955a819bf239dbc52Ye Wen    protected Uri mMessageUri;
96b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen    // The reference to the pending requests manager (i.e. the MmsService)
97b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen    protected RequestManager mRequestManager;
9818aabe2742cbaffc3c8293cfb3ce2841fe82326dYe Wen    // The SIM id
9918aabe2742cbaffc3c8293cfb3ce2841fe82326dYe Wen    protected long mSubId;
10018aabe2742cbaffc3c8293cfb3ce2841fe82326dYe Wen    // The creator app
10118aabe2742cbaffc3c8293cfb3ce2841fe82326dYe Wen    protected String mCreator;
102c984707ecf54d545a4a5809c6ce1d18bf7cee61eYe Wen    // MMS config
103c984707ecf54d545a4a5809c6ce1d18bf7cee61eYe Wen    protected MmsConfig.Overridden mMmsConfig;
104b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen
105b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen    // Intent result receiver for carrier app
106b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen    protected final BroadcastReceiver mCarrierAppResultReceiver = new BroadcastReceiver() {
107b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen        @Override
108b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen        public void onReceive(Context context, Intent intent) {
109b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen            final String action = intent.getAction();
110b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen            if (action.equals(Telephony.Mms.Intents.MMS_SEND_ACTION) ||
111b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen                    action.equals(Telephony.Mms.Intents.MMS_DOWNLOAD_ACTION)) {
112b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen                Log.d(MmsService.TAG, "Carrier app result for " + action);
113b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen                final int rc = getResultCode();
114b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen                if (rc == Activity.RESULT_OK) {
115b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen                    // Handled by carrier app, waiting for result
116b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen                    Log.d(MmsService.TAG, "Sending/downloading MMS by IP pending.");
117b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen                    final Bundle resultExtras = getResultExtras(false);
118b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen                    if (resultExtras != null && resultExtras.containsKey(EXTRA_MESSAGE_REF)) {
119b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen                        final int ref = resultExtras.getInt(EXTRA_MESSAGE_REF);
120b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen                        Log.d(MmsService.TAG, "messageref = " + ref);
121b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen                        mRequestManager.addPending(ref, MmsRequest.this);
122b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen                    } else {
123b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen                        // Bad, no message ref provided
124b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen                        Log.e(MmsService.TAG, "Can't find messageref in result extras.");
125b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen                    }
126b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen                } else {
127b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen                    // No carrier app present, sending normally
128b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen                    Log.d(MmsService.TAG, "Sending/downloading MMS by IP failed.");
129b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen                    mRequestManager.addRunning(MmsRequest.this);
130b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen                }
131b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen            } else {
132b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen                Log.e(MmsService.TAG, "unexpected BroadcastReceiver action: " + action);
133b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen            }
134b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen
135b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen        }
136b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen    };
137b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen
138b83f2faa04dc275b6779644308384459ffcff63fJulian Odell    public MmsRequest(RequestManager requestManager, Uri messageUri, long subId,
1393e40f4c4a8c82e795a5cea235d52eacd177c0a69Ye Wen            String creator, Bundle configOverrides) {
140b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen        mRequestManager = requestManager;
14118aabe2742cbaffc3c8293cfb3ce2841fe82326dYe Wen        mMessageUri = messageUri;
14218aabe2742cbaffc3c8293cfb3ce2841fe82326dYe Wen        mSubId = subId;
14318aabe2742cbaffc3c8293cfb3ce2841fe82326dYe Wen        mCreator = creator;
14476b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor        mMmsConfig = new MmsConfig.Overridden(
14576b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor                MmsConfigManager.getInstance().getMmsConfigBySubId(subId),
14676b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor                configOverrides);
147b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen    }
1483a14e46a22e95062102a19c955a819bf239dbc52Ye Wen
149b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen    /**
150b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen     * Execute the request
151b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen     *
152b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen     * @param context The context
153b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen     * @param networkManager The network manager to use
154b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen     */
155c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    public void execute(Context context, MmsNetworkManager networkManager) {
156b83f2faa04dc275b6779644308384459ffcff63fJulian Odell        int result = SmsManager.MMS_ERROR_IO_ERROR;
157c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen        byte[] response = null;
158b83f2faa04dc275b6779644308384459ffcff63fJulian Odell
159b83f2faa04dc275b6779644308384459ffcff63fJulian Odell        if (prepareForHttpRequest()) {
160b83f2faa04dc275b6779644308384459ffcff63fJulian Odell            long retryDelay = 2;
161b83f2faa04dc275b6779644308384459ffcff63fJulian Odell            // Try multiple times of MMS HTTP request
162b83f2faa04dc275b6779644308384459ffcff63fJulian Odell            for (int i = 0; i < RETRY_TIMES; i++) {
163c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen                try {
164b83f2faa04dc275b6779644308384459ffcff63fJulian Odell                    networkManager.acquireNetwork();
165b83f2faa04dc275b6779644308384459ffcff63fJulian Odell                    try {
166b83f2faa04dc275b6779644308384459ffcff63fJulian Odell                        final ApnSettings apn = ApnSettings.load(context, null/*apnName*/, mSubId);
167b83f2faa04dc275b6779644308384459ffcff63fJulian Odell                        response = doHttp(context, networkManager, apn);
168b83f2faa04dc275b6779644308384459ffcff63fJulian Odell                        result = Activity.RESULT_OK;
169b83f2faa04dc275b6779644308384459ffcff63fJulian Odell                        // Success
170b83f2faa04dc275b6779644308384459ffcff63fJulian Odell                        break;
171b83f2faa04dc275b6779644308384459ffcff63fJulian Odell                    } finally {
172b83f2faa04dc275b6779644308384459ffcff63fJulian Odell                        networkManager.releaseNetwork();
173b83f2faa04dc275b6779644308384459ffcff63fJulian Odell                    }
174b83f2faa04dc275b6779644308384459ffcff63fJulian Odell                } catch (ApnException e) {
175b83f2faa04dc275b6779644308384459ffcff63fJulian Odell                    Log.e(MmsService.TAG, "MmsRequest: APN failure", e);
176b83f2faa04dc275b6779644308384459ffcff63fJulian Odell                    result = SmsManager.MMS_ERROR_INVALID_APN;
177b83f2faa04dc275b6779644308384459ffcff63fJulian Odell                    break;
178b83f2faa04dc275b6779644308384459ffcff63fJulian Odell                } catch (MmsNetworkException e) {
179b83f2faa04dc275b6779644308384459ffcff63fJulian Odell                    Log.e(MmsService.TAG, "MmsRequest: MMS network acquiring failure", e);
180b83f2faa04dc275b6779644308384459ffcff63fJulian Odell                    result = SmsManager.MMS_ERROR_UNABLE_CONNECT_MMS;
181b83f2faa04dc275b6779644308384459ffcff63fJulian Odell                    // Retry
182b83f2faa04dc275b6779644308384459ffcff63fJulian Odell                } catch (MmsHttpException e) {
183b83f2faa04dc275b6779644308384459ffcff63fJulian Odell                    Log.e(MmsService.TAG, "MmsRequest: HTTP or network I/O failure", e);
184b83f2faa04dc275b6779644308384459ffcff63fJulian Odell                    result = SmsManager.MMS_ERROR_HTTP_FAILURE;
185b83f2faa04dc275b6779644308384459ffcff63fJulian Odell                    // Retry
186b83f2faa04dc275b6779644308384459ffcff63fJulian Odell                } catch (Exception e) {
187b83f2faa04dc275b6779644308384459ffcff63fJulian Odell                    Log.e(MmsService.TAG, "MmsRequest: unexpected failure", e);
188b83f2faa04dc275b6779644308384459ffcff63fJulian Odell                    result = SmsManager.MMS_ERROR_UNSPECIFIED;
189c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen                    break;
190c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen                }
191b83f2faa04dc275b6779644308384459ffcff63fJulian Odell                try {
192b83f2faa04dc275b6779644308384459ffcff63fJulian Odell                    Thread.sleep(retryDelay * 1000, 0/*nano*/);
193b83f2faa04dc275b6779644308384459ffcff63fJulian Odell                } catch (InterruptedException e) {}
194b83f2faa04dc275b6779644308384459ffcff63fJulian Odell                retryDelay <<= 1;
195c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen            }
196c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen        }
197b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen        processResult(context, result, response);
198b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen    }
199b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen
200b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen    /**
201b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     * Try running MMS HTTP request for all the addresses that we can resolve to
202b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     *
203b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     * @param context The context
204b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     * @param netMgr The {@link com.android.mms.service.MmsNetworkManager}
205b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     * @param url The HTTP URL
206b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     * @param pdu The PDU to send
207b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     * @param method The HTTP method to use
208b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     * @param apn The APN setting to use
209b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     * @return The response data
210b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     * @throws MmsHttpException If there is any HTTP/network failure
211b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     */
212b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen    protected byte[] doHttpForResolvedAddresses(Context context, MmsNetworkManager netMgr,
213b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen            String url, byte[] pdu, int method, ApnSettings apn) throws MmsHttpException {
214b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen        MmsHttpException lastException = null;
215b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen        final ConnectivityManager connMgr =
216b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
217b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen        // Do HTTP on all the addresses we can resolve to
218b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen        for (final InetAddress address : resolveDestination(connMgr, netMgr, url, apn)) {
219b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen            try {
220b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                // TODO: we have to use a deprecated API here because with the new
221b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                // ConnectivityManager APIs in LMP, we need to either use a bound process
222b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                // or a bound socket. The former can not be used since we share the
223b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                // phone process with others. The latter is not supported by any HTTP
224b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                // library yet. We have to rely on this API to get things work. Once
225b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                // a multinet aware HTTP lib is ready, we should switch to that and
226b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                // remove all the unnecessary code.
227b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                if (!connMgr.requestRouteToHostAddress(
228b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                        ConnectivityManager.TYPE_MOBILE_MMS, address)) {
229b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                    throw new MmsHttpException("MmsRequest: can not request a route for host "
230b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                            + address);
231b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                }
232b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                return HttpUtils.httpConnection(
233b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                        context,
234b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                        url,
235b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                        pdu,
236b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                        method,
237b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                        apn.isProxySet(),
238b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                        apn.getProxyAddress(),
239b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                        apn.getProxyPort(),
240b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                        netMgr,
241c984707ecf54d545a4a5809c6ce1d18bf7cee61eYe Wen                        address instanceof Inet6Address,
242c984707ecf54d545a4a5809c6ce1d18bf7cee61eYe Wen                        mMmsConfig);
243b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen            } catch (MmsHttpException e) {
244b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                lastException = e;
245b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                Log.e(MmsService.TAG, "MmsRequest: failure in trying address " + address, e);
246b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen            }
247b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen        }
248b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen        if (lastException != null) {
249b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen            throw lastException;
250b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen        } else {
251b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen            // Should not reach here
252b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen            throw new MmsHttpException("MmsRequest: unknown failure");
253b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen        }
254b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen    }
255b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen
256b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen    /**
257b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     * Resolve the name of the host we are about to connect to, which can be the URL host or
258b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     * the proxy host. We only resolve to the supported address types (IPv4 or IPv6 or both)
259b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     * based on the MMS network interface's address type, i.e. we only need addresses that
260b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     * match the link address type.
261b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     *
262b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     * @param connMgr The connectivity manager
263b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     * @param netMgr The current {@link MmsNetworkManager}
264b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     * @param url The HTTP URL
265b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     * @param apn The APN setting to use
266b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     * @return A list of matching resolved addresses
267b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     * @throws MmsHttpException For any network failure
268b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     */
269b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen    private static List<InetAddress> resolveDestination(ConnectivityManager connMgr,
270b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen            MmsNetworkManager netMgr, String url, ApnSettings apn) throws MmsHttpException {
271b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen        Log.d(MmsService.TAG, "MmsRequest: resolve url " + url);
272b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen        // Find the real host to connect to
273b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen        String host = null;
274b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen        if (apn.isProxySet()) {
275b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen            host = apn.getProxyAddress();
276b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen        } else {
277b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen            final Uri uri = Uri.parse(url);
278b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen            host = uri.getHost();
279b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen        }
280b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen        // Find out the link address types: ipv4 or ipv6 or both
281b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen        final int addressTypes = getMmsLinkAddressTypes(connMgr, netMgr.getNetwork());
282b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen        Log.d(MmsService.TAG, "MmsRequest: addressTypes=" + addressTypes);
283b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen        // Resolve the host to a list of addresses based on supported address types
284b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen        return resolveHostName(netMgr, host, addressTypes);
285b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen    }
286b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen
287b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen    // Address type masks
288b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen    private static final int ADDRESS_TYPE_IPV4 = 1;
289b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen    private static final int ADDRESS_TYPE_IPV6 = 1 << 1;
290b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen
291b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen    /**
292b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     * Try to find out if we should use IPv6 or IPv4 for MMS. Basically we check if the MMS
293b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     * network interface has IPv6 address or not. If so, we will use IPv6. Otherwise, use
294b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     * IPv4.
295b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     *
296b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     * @param connMgr The connectivity manager
297b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     * @return A bit mask indicating what address types we have
298b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     */
299b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen    private static int getMmsLinkAddressTypes(ConnectivityManager connMgr, Network network) {
300b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen        int result = 0;
301b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen        // Return none if network is not available
302b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen        if (network == null) {
303b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen            return result;
304b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen        }
305b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen        final LinkProperties linkProperties = connMgr.getLinkProperties(network);
306b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen        if (linkProperties != null) {
307b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen            for (InetAddress addr : linkProperties.getAddresses()) {
308b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                if (addr instanceof Inet4Address) {
309b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                    result |= ADDRESS_TYPE_IPV4;
310b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                } else if (addr instanceof Inet6Address) {
311b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                    result |= ADDRESS_TYPE_IPV6;
312b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                }
313b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen            }
314b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen        }
315b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen        return result;
316b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen    }
317b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen
318b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen    /**
319b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     * Resolve host name to address by specified address types.
320b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     *
321b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     * @param netMgr The current {@link MmsNetworkManager}
322b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     * @param host The host name
323b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     * @param addressTypes The required address type in a bit mask
324b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     *  (0x01: IPv4, 0x10: IPv6, 0x11: both)
325b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     * @return
326b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     * @throws MmsHttpException
327b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     */
328b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen    private static List<InetAddress> resolveHostName(MmsNetworkManager netMgr, String host,
329b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen            int addressTypes) throws MmsHttpException {
330b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen        final List<InetAddress> resolved = new ArrayList<InetAddress>();
331b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen        try {
332b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen            if (addressTypes != 0) {
333b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                for (final InetAddress addr : netMgr.getAllByName(host)) {
334b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                    if ((addressTypes & ADDRESS_TYPE_IPV6) != 0
335b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                            && addr instanceof Inet6Address) {
336b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                        // Should use IPv6 and this is IPv6 address, add it
337b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                        resolved.add(addr);
338b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                    } else if ((addressTypes & ADDRESS_TYPE_IPV4) != 0
339b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                            && addr instanceof Inet4Address) {
340b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                        // Should use IPv4 and this is IPv4 address, add it
341b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                        resolved.add(addr);
342b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                    }
343b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                }
344b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen            }
345b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen            if (resolved.size() < 1) {
346b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                throw new MmsHttpException("Failed to resolve " + host
347b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen                        + " for allowed address types: " + addressTypes);
348b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen            }
349b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen            return resolved;
350b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen        } catch (final UnknownHostException e) {
351b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen            throw new MmsHttpException("Failed to resolve " + host, e);
352b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen        }
353b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen    }
354b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen
355b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen    /**
356b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen     * Process the result of the completed request, including updating the message status
357b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen     * in database and sending back the result via pending intents.
358b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen     *
359b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen     * @param context The context
360b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen     * @param result The result code of execution
361b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen     * @param response The response body
362b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen     */
363b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen    public void processResult(Context context, int result, byte[] response) {
364b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen        updateStatus(context, result, response);
3653a14e46a22e95062102a19c955a819bf239dbc52Ye Wen
366c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen        // Return MMS HTTP request result via PendingIntent
367c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen        final PendingIntent pendingIntent = getPendingIntent();
368c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen        if (pendingIntent != null) {
369b83f2faa04dc275b6779644308384459ffcff63fJulian Odell            boolean succeeded = true;
3703a14e46a22e95062102a19c955a819bf239dbc52Ye Wen            // Extra information to send back with the pending intent
3713a14e46a22e95062102a19c955a819bf239dbc52Ye Wen            Intent fillIn = new Intent();
372c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen            if (response != null) {
373b83f2faa04dc275b6779644308384459ffcff63fJulian Odell                succeeded = transferResponse(fillIn, response);
3743a14e46a22e95062102a19c955a819bf239dbc52Ye Wen            }
3753a14e46a22e95062102a19c955a819bf239dbc52Ye Wen            if (mMessageUri != null) {
3763a14e46a22e95062102a19c955a819bf239dbc52Ye Wen                fillIn.putExtra("uri", mMessageUri.toString());
377c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen            }
378c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen            try {
379b83f2faa04dc275b6779644308384459ffcff63fJulian Odell                if (!succeeded) {
380b83f2faa04dc275b6779644308384459ffcff63fJulian Odell                    result = SmsManager.MMS_ERROR_IO_ERROR;
381b83f2faa04dc275b6779644308384459ffcff63fJulian Odell                }
3823a14e46a22e95062102a19c955a819bf239dbc52Ye Wen                pendingIntent.send(context, result, fillIn);
383c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen            } catch (PendingIntent.CanceledException e) {
384c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen                Log.e(MmsService.TAG, "MmsRequest: sending pending intent canceled", e);
385c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen            }
386c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen        }
387b2823fa889f5c1bde4047af36b3b07672942f700Julian Odell
388b2823fa889f5c1bde4047af36b3b07672942f700Julian Odell        revokeUriPermission(context);
389c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    }
390c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen
3913a14e46a22e95062102a19c955a819bf239dbc52Ye Wen    /**
3923a14e46a22e95062102a19c955a819bf239dbc52Ye Wen     * Making the HTTP request to MMSC
3933a14e46a22e95062102a19c955a819bf239dbc52Ye Wen     *
3943a14e46a22e95062102a19c955a819bf239dbc52Ye Wen     * @param context The context
395b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen     * @param netMgr The current {@link MmsNetworkManager}
3963a14e46a22e95062102a19c955a819bf239dbc52Ye Wen     * @param apn The APN setting
3973a14e46a22e95062102a19c955a819bf239dbc52Ye Wen     * @return The HTTP response data
3983a14e46a22e95062102a19c955a819bf239dbc52Ye Wen     * @throws MmsHttpException If any network error happens
3993a14e46a22e95062102a19c955a819bf239dbc52Ye Wen     */
400b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen    protected abstract byte[] doHttp(Context context, MmsNetworkManager netMgr, ApnSettings apn)
401b07ae2f78ac69a1e7bcfb1ce62e69d7283b46295Ye Wen            throws MmsHttpException;
402c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen
4033a14e46a22e95062102a19c955a819bf239dbc52Ye Wen    /**
4043a14e46a22e95062102a19c955a819bf239dbc52Ye Wen     * @return The PendingIntent associate with the MMS sending invocation
4053a14e46a22e95062102a19c955a819bf239dbc52Ye Wen     */
406c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen    protected abstract PendingIntent getPendingIntent();
4073a14e46a22e95062102a19c955a819bf239dbc52Ye Wen
4083a14e46a22e95062102a19c955a819bf239dbc52Ye Wen    /**
409b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen     * @return The running queue should be used by this request
4103a14e46a22e95062102a19c955a819bf239dbc52Ye Wen     */
411b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen    protected abstract int getRunningQueue();
4123a14e46a22e95062102a19c955a819bf239dbc52Ye Wen
4133a14e46a22e95062102a19c955a819bf239dbc52Ye Wen    /**
414b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen     * Update database status of the message represented by this request
4153a14e46a22e95062102a19c955a819bf239dbc52Ye Wen     *
4163a14e46a22e95062102a19c955a819bf239dbc52Ye Wen     * @param context The context
4173a14e46a22e95062102a19c955a819bf239dbc52Ye Wen     * @param result The result code of execution
418b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen     * @param response The response body
4193a14e46a22e95062102a19c955a819bf239dbc52Ye Wen     */
420b786d3ea3daf4a91119ea06c532fe7ef5835944cYe Wen    protected abstract void updateStatus(Context context, int result, byte[] response);
421b83f2faa04dc275b6779644308384459ffcff63fJulian Odell
422b83f2faa04dc275b6779644308384459ffcff63fJulian Odell    /**
423b83f2faa04dc275b6779644308384459ffcff63fJulian Odell     * Prepare to make the HTTP request - will download message for sending
424b83f2faa04dc275b6779644308384459ffcff63fJulian Odell     * @return true if preparation succeeds (and request can proceed) else false
425b83f2faa04dc275b6779644308384459ffcff63fJulian Odell     */
426b83f2faa04dc275b6779644308384459ffcff63fJulian Odell    protected abstract boolean prepareForHttpRequest();
427b83f2faa04dc275b6779644308384459ffcff63fJulian Odell
428b83f2faa04dc275b6779644308384459ffcff63fJulian Odell    /**
429b83f2faa04dc275b6779644308384459ffcff63fJulian Odell     * Transfer the received response to the caller
430b83f2faa04dc275b6779644308384459ffcff63fJulian Odell     *
431b83f2faa04dc275b6779644308384459ffcff63fJulian Odell     * @param fillIn the intent that will be returned to the caller
432b83f2faa04dc275b6779644308384459ffcff63fJulian Odell     * @param response the pdu to transfer
433b83f2faa04dc275b6779644308384459ffcff63fJulian Odell     * @return true if response transfer succeeds else false
434b83f2faa04dc275b6779644308384459ffcff63fJulian Odell     */
435b83f2faa04dc275b6779644308384459ffcff63fJulian Odell    protected abstract boolean transferResponse(Intent fillIn, byte[] response);
436f6d88a72cd01ecaf9f0319249e239afc008f1ac8Cheuksan Wang
437f6d88a72cd01ecaf9f0319249e239afc008f1ac8Cheuksan Wang    /**
438f6d88a72cd01ecaf9f0319249e239afc008f1ac8Cheuksan Wang     * Revoke the content URI permission granted by the MMS app to the phone package.
439f6d88a72cd01ecaf9f0319249e239afc008f1ac8Cheuksan Wang     *
440f6d88a72cd01ecaf9f0319249e239afc008f1ac8Cheuksan Wang     * @param context The context
441f6d88a72cd01ecaf9f0319249e239afc008f1ac8Cheuksan Wang     */
442f6d88a72cd01ecaf9f0319249e239afc008f1ac8Cheuksan Wang    protected abstract void revokeUriPermission(Context context);
443c91cc9d4a5aa12a570a3b35a12b3e34a6a9eeb51Ye Wen}
444