Loading android-smsmms/src/main/java/com/android/mms/service_alt/ApnSettings.javadeleted 100755 → 0 +0 −240 Original line number Diff line number Diff line /* * Copyright (C) 2015 Jacob Klinker * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.mms.service_alt; import android.content.Context; import android.content.SharedPreferences; import android.database.Cursor; import android.database.sqlite.SqliteWrapper; import android.net.NetworkUtilsHelper; import android.net.Uri; import android.preference.PreferenceManager; import android.provider.Telephony; import android.text.TextUtils; import com.android.mms.service_alt.exception.ApnException; import timber.log.Timber; import java.net.URI; import java.net.URISyntaxException; /** * APN settings used for MMS transactions */ public class ApnSettings { // MMSC URL private final String mServiceCenter; // MMSC proxy address private final String mProxyAddress; // MMSC proxy port private final int mProxyPort; // Debug text for this APN: a concatenation of interesting columns of this APN private final String mDebugText; private static final String[] APN_PROJECTION = { Telephony.Carriers.TYPE, Telephony.Carriers.MMSC, Telephony.Carriers.MMSPROXY, Telephony.Carriers.MMSPORT, Telephony.Carriers.NAME, Telephony.Carriers.APN, Telephony.Carriers.BEARER, Telephony.Carriers.PROTOCOL, Telephony.Carriers.ROAMING_PROTOCOL, Telephony.Carriers.AUTH_TYPE, Telephony.Carriers.MVNO_TYPE, Telephony.Carriers.MVNO_MATCH_DATA, Telephony.Carriers.PROXY, Telephony.Carriers.PORT, Telephony.Carriers.SERVER, Telephony.Carriers.USER, Telephony.Carriers.PASSWORD, }; private static final int COLUMN_TYPE = 0; private static final int COLUMN_MMSC = 1; private static final int COLUMN_MMSPROXY = 2; private static final int COLUMN_MMSPORT = 3; private static final int COLUMN_NAME = 4; private static final int COLUMN_APN = 5; private static final int COLUMN_BEARER = 6; private static final int COLUMN_PROTOCOL = 7; private static final int COLUMN_ROAMING_PROTOCOL = 8; private static final int COLUMN_AUTH_TYPE = 9; private static final int COLUMN_MVNO_TYPE = 10; private static final int COLUMN_MVNO_MATCH_DATA = 11; private static final int COLUMN_PROXY = 12; private static final int COLUMN_PORT = 13; private static final int COLUMN_SERVER = 14; private static final int COLUMN_USER = 15; private static final int COLUMN_PASSWORD = 16; /** * Load APN settings from system * * @param context * @param apnName the optional APN name to match */ public static ApnSettings load(Context context, String apnName, int subId) throws ApnException { SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context); String mmsc = sharedPrefs.getString("mmsc_url", ""); if (!TextUtils.isEmpty(mmsc)) { String mmsProxy = sharedPrefs.getString("mms_proxy", ""); String mmsPort = sharedPrefs.getString("mms_port", ""); return new ApnSettings(mmsc, mmsProxy, parsePort(mmsPort), "Default from settings"); } Timber.v("ApnSettings: apnName " + apnName); // TODO: CURRENT semantics is currently broken in telephony. Revive this when it is fixed. //String selection = Telephony.Carriers.CURRENT + " IS NOT NULL"; String selection = null; String[] selectionArgs = null; apnName = apnName != null ? apnName.trim() : null; if (!TextUtils.isEmpty(apnName)) { //selection += " AND " + Telephony.Carriers.APN + "=?"; selection = Telephony.Carriers.APN + "=?"; selectionArgs = new String[]{ apnName }; } Cursor cursor = null; try { cursor = SqliteWrapper.query( context, context.getContentResolver(), Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "/subId/" + subId), APN_PROJECTION, selection, selectionArgs, null/*sortOrder*/); if (cursor != null) { String mmscUrl = null; String proxyAddress = null; int proxyPort = -1; while (cursor.moveToNext()) { // Read values from APN settings if (isValidApnType( cursor.getString(COLUMN_TYPE), "mms")) { mmscUrl = trimWithNullCheck(cursor.getString(COLUMN_MMSC)); if (TextUtils.isEmpty(mmscUrl)) { continue; } mmscUrl = NetworkUtilsHelper.trimV4AddrZeros(mmscUrl); try { new URI(mmscUrl); } catch (URISyntaxException e) { throw new ApnException("Invalid MMSC url " + mmscUrl); } proxyAddress = trimWithNullCheck(cursor.getString(COLUMN_MMSPROXY)); if (!TextUtils.isEmpty(proxyAddress)) { proxyAddress = NetworkUtilsHelper.trimV4AddrZeros(proxyAddress); final String portString = trimWithNullCheck(cursor.getString(COLUMN_MMSPORT)); if (portString != null) { try { proxyPort = Integer.parseInt(portString); } catch (NumberFormatException e) { Timber.e("Invalid port " + portString); throw new ApnException("Invalid port " + portString); } } } return new ApnSettings( mmscUrl, proxyAddress, proxyPort, getDebugText(cursor)); } } } } finally { if (cursor != null) { cursor.close(); } } return new ApnSettings("", "", 80, "Failed to find APNs :("); } private static String getDebugText(Cursor cursor) { final StringBuilder sb = new StringBuilder(); sb.append("APN ["); for (int i = 0; i < cursor.getColumnCount(); i++) { final String name = cursor.getColumnName(i); final String value = cursor.getString(i); if (TextUtils.isEmpty(value)) { continue; } if (i > 0) { sb.append(' '); } sb.append(name).append('=').append(value); } sb.append("]"); return sb.toString(); } private static String trimWithNullCheck(String value) { return value != null ? value.trim() : null; } public ApnSettings(String mmscUrl, String proxyAddr, int proxyPort, String debugText) { mServiceCenter = mmscUrl; mProxyAddress = proxyAddr; mProxyPort = proxyPort; mDebugText = debugText; } public String getMmscUrl() { return mServiceCenter; } public String getProxyAddress() { return mProxyAddress; } public int getProxyPort() { return mProxyPort; } public boolean isProxySet() { return !TextUtils.isEmpty(mProxyAddress); } private static boolean isValidApnType(String types, String requestType) { // If APN type is unspecified, assume APN_TYPE_ALL. if (TextUtils.isEmpty(types)) { return true; } for (String type : types.split(",")) { type = type.trim(); if (type.equals(requestType) || type.equals("*")) { return true; } } return false; } private static int parsePort(String port) { if (TextUtils.isEmpty(port)) { return 80; } else { return Integer.parseInt(port); } } public String toString() { return mDebugText; } } android-smsmms/src/main/java/com/android/mms/service_alt/DownloadRequest.java +0 −74 Original line number Diff line number Diff line Loading @@ -28,7 +28,6 @@ import android.os.Bundle; import android.provider.Telephony; import android.text.TextUtils; import com.android.mms.service_alt.exception.MmsHttpException; import com.google.android.mms.MmsException; import com.google.android.mms.pdu_alt.GenericPdu; import com.google.android.mms.pdu_alt.PduHeaders; Loading Loading @@ -75,44 +74,6 @@ public class DownloadRequest extends MmsRequest { mContentUri = contentUri; } @Override protected byte[] doHttp(Context context, MmsNetworkManager netMgr, ApnSettings apn) throws MmsHttpException { final MmsHttpClient mmsHttpClient = netMgr.getOrCreateHttpClient(); if (mmsHttpClient == null) { Timber.e("MMS network is not ready!"); throw new MmsHttpException(0/*statusCode*/, "MMS network is not ready"); } return mmsHttpClient.execute( mLocationUrl, null/*pud*/, MmsHttpClient.METHOD_GET, apn.isProxySet(), apn.getProxyAddress(), apn.getProxyPort(), mMmsConfig); } @Override protected PendingIntent getPendingIntent() { return mDownloadedIntent; } @Override protected int getQueueType() { return 1; } @Override protected Uri persistIfRequired(Context context, int result, byte[] response) { if (!mRequestManager.getAutoPersistingPref()) { notifyOfDownload(context); return null; } return persist(context, response, mMmsConfig, mLocationUrl, mSubId, mCreator); } public static Uri persist(Context context, byte[] response, MmsConfig.Overridden mmsConfig, String locationUrl, int subId, String creator) { // Let any mms apps running as secondary user know that a new mms has been downloaded. Loading Loading @@ -266,41 +227,6 @@ public class DownloadRequest extends MmsRequest { // } } /** * Transfer the received response to the caller (for download requests write to content uri) * * @param fillIn the intent that will be returned to the caller * @param response the pdu to transfer */ @Override protected boolean transferResponse(Intent fillIn, final byte[] response) { return mRequestManager.writePduToContentUri(mContentUri, response); } @Override protected boolean prepareForHttpRequest() { return true; } /** * Try downloading via the carrier app. * * @param context The context * @param carrierMessagingServicePackage The carrier messaging service handling the download */ public void tryDownloadingByCarrierApp(Context context, String carrierMessagingServicePackage) { // final CarrierDownloadManager carrierDownloadManger = new CarrierDownloadManager(); // final CarrierDownloadCompleteCallback downloadCallback = // new CarrierDownloadCompleteCallback(context, carrierDownloadManger); // carrierDownloadManger.downloadMms(context, carrierMessagingServicePackage, // downloadCallback); } @Override protected void revokeUriPermission(Context context) { context.revokeUriPermission(mContentUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION); } private String getContentLocation(Context context, Uri uri) throws MmsException { Cursor cursor = android.database.sqlite.SqliteWrapper.query(context, context.getContentResolver(), Loading android-smsmms/src/main/java/com/android/mms/service_alt/MmsRequest.java +1 −276 Original line number Diff line number Diff line Loading @@ -16,32 +16,19 @@ package com.android.mms.service_alt; import android.app.Activity; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.Uri; import android.net.wifi.WifiManager; import android.os.Build; import android.os.Bundle; import android.provider.Settings; import android.service.carrier.CarrierMessagingService; import android.telephony.SmsManager; import android.telephony.TelephonyManager; import com.android.mms.service_alt.exception.ApnException; import com.android.mms.service_alt.exception.MmsHttpException; import com.klinker.android.send_message.Utils; import timber.log.Timber; /** * Base class for MMS requests. This has the common logic of sending/downloading MMS. */ public abstract class MmsRequest { private static final int RETRY_TIMES = 3; /** * Interface for certain functionalities from MmsService */ Loading Loading @@ -86,8 +73,6 @@ public abstract class MmsRequest { // MMS config overrides protected Bundle mMmsConfigOverrides; private boolean mobileDataEnabled; public MmsRequest(RequestManager requestManager, int subId, String creator, Bundle configOverrides) { mRequestManager = requestManager; Loading @@ -101,180 +86,6 @@ public abstract class MmsRequest { return mSubId; } private boolean ensureMmsConfigLoaded() { if (mMmsConfig == null) { final MmsConfig config; // Not yet retrieved from mms config manager. Try getting it. config = MmsConfigManager.getInstance().getMmsConfigBySubId(mSubId); if (config != null) { mMmsConfig = new MmsConfig.Overridden(config, mMmsConfigOverrides); } } return mMmsConfig != null; } private static boolean inAirplaneMode(final Context context) { return Settings.System.getInt(context.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0) != 0; } private static boolean isMobileDataEnabled(final Context context, final int subId) { final TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); return Utils.isDataEnabled(telephonyManager, subId); } private static boolean isDataNetworkAvailable(final Context context, final int subId) { return !inAirplaneMode(context) && isMobileDataEnabled(context, subId); } /** * Execute the request * * @param context The context * @param networkManager The network manager to use */ public void execute(Context context, MmsNetworkManager networkManager) { int result = SmsManager.MMS_ERROR_UNSPECIFIED; int httpStatusCode = 0; byte[] response = null; WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); boolean isWifiEnabled = wifi.isWifiEnabled(); if (!useWifi(context)) { wifi.setWifiEnabled(false); } mobileDataEnabled = Utils.isMobileDataEnabled(context); Timber.v("mobile data enabled: " + mobileDataEnabled); if (!mobileDataEnabled && !useWifi(context)) { Timber.v("mobile data not enabled, so forcing it to enable"); Utils.setMobileDataEnabled(context, true); } if (!ensureMmsConfigLoaded()) { // Check mms config Timber.e("MmsRequest: mms config is not loaded yet"); result = SmsManager.MMS_ERROR_CONFIGURATION_ERROR; } else if (!prepareForHttpRequest()) { // Prepare request, like reading pdu data from user Timber.e("MmsRequest: failed to prepare for request"); result = SmsManager.MMS_ERROR_IO_ERROR; } else if (!isDataNetworkAvailable(context, mSubId)) { Timber.e("MmsRequest: in airplane mode or mobile data disabled"); result = SmsManager.MMS_ERROR_NO_DATA_NETWORK; } else { // Execute long retryDelaySecs = 2; // Try multiple times of MMS HTTP request for (int i = 0; i < RETRY_TIMES; i++) { try { try { networkManager.acquireNetwork(); } catch (Exception e) { Timber.e(e, "error acquiring network"); } final String apnName = networkManager.getApnName(); try { ApnSettings apn = null; try { apn = ApnSettings.load(context, apnName, mSubId); } catch (ApnException e) { // If no APN could be found, fall back to trying without the APN name if (apnName == null) { // If the APN name was already null then don't need to retry throw (e); } Timber.i("MmsRequest: No match with APN name:" + apnName + ", try with no name"); apn = ApnSettings.load(context, null, mSubId); } Timber.i("MmsRequest: using " + apn.toString()); response = doHttp(context, networkManager, apn); result = Activity.RESULT_OK; // Success break; } finally { networkManager.releaseNetwork(); } } catch (ApnException e) { Timber.e(e, "MmsRequest: APN failure"); result = SmsManager.MMS_ERROR_INVALID_APN; break; // } catch (MmsNetworkException e) { // Timber.e(e, "MmsRequest: MMS network acquiring failure"); // result = SmsManager.MMS_ERROR_UNABLE_CONNECT_MMS; // // Retry } catch (MmsHttpException e) { Timber.e(e, "MmsRequest: HTTP or network I/O failure"); result = SmsManager.MMS_ERROR_HTTP_FAILURE; httpStatusCode = e.getStatusCode(); // Retry } catch (Exception e) { Timber.e(e, "MmsRequest: unexpected failure"); result = SmsManager.MMS_ERROR_UNSPECIFIED; break; } try { Thread.sleep(retryDelaySecs * 1000, 0/*nano*/); } catch (InterruptedException e) { } retryDelaySecs <<= 1; } } if (!mobileDataEnabled) { Timber.v("setting mobile data back to disabled"); Utils.setMobileDataEnabled(context, false); } if (!useWifi(context)) { wifi.setWifiEnabled(isWifiEnabled); } processResult(context, result, response, httpStatusCode); } /** * Process the result of the completed request, including updating the message status * in database and sending back the result via pending intents. * @param context The context * @param result The result code of execution * @param response The response body * @param httpStatusCode The optional http status code in case of http failure */ public void processResult(Context context, int result, byte[] response, int httpStatusCode) { final Uri messageUri = persistIfRequired(context, result, response); // Return MMS HTTP request result via PendingIntent final PendingIntent pendingIntent = getPendingIntent(); if (pendingIntent != null) { boolean succeeded = true; // Extra information to send back with the pending intent Intent fillIn = new Intent(); if (response != null) { succeeded = transferResponse(fillIn, response); } if (messageUri != null) { fillIn.putExtra("uri", messageUri.toString()); } if (result == SmsManager.MMS_ERROR_HTTP_FAILURE && httpStatusCode != 0) { fillIn.putExtra(SmsManager.EXTRA_MMS_HTTP_STATUS, httpStatusCode); } try { if (!succeeded) { result = SmsManager.MMS_ERROR_IO_ERROR; } pendingIntent.send(context, result, fillIn); } catch (PendingIntent.CanceledException e) { Timber.e(e, "MmsRequest: sending pending intent canceled"); } } revokeUriPermission(context); } /** * are we set up to use wifi? if so, send mms over it. */ Loading @@ -291,90 +102,4 @@ public abstract class MmsRequest { return false; } /** * Returns true if sending / downloading using the carrier app has failed and completes the * action using platform API's, otherwise false. */ protected boolean maybeFallbackToRegularDelivery(int carrierMessagingAppResult) { if (carrierMessagingAppResult == CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK || carrierMessagingAppResult == CarrierMessagingService.DOWNLOAD_STATUS_RETRY_ON_CARRIER_NETWORK) { Timber.d("Sending/downloading MMS by IP failed."); mRequestManager.addSimRequest(MmsRequest.this); return true; } else { return false; } } /** * Converts from {@code carrierMessagingAppResult} to a platform result code. */ protected static int toSmsManagerResult(int carrierMessagingAppResult) { switch (carrierMessagingAppResult) { case CarrierMessagingService.SEND_STATUS_OK: return Activity.RESULT_OK; case CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK: return SmsManager.MMS_ERROR_RETRY; default: return SmsManager.MMS_ERROR_UNSPECIFIED; } } /** * Making the HTTP request to MMSC * * @param context The context * @param netMgr The current {@link MmsNetworkManager} * @param apn The APN setting * @return The HTTP response data * @throws MmsHttpException If any network error happens */ protected abstract byte[] doHttp(Context context, MmsNetworkManager netMgr, ApnSettings apn) throws MmsHttpException; /** * @return The PendingIntent associate with the MMS sending invocation */ protected abstract PendingIntent getPendingIntent(); /** * @return The queue should be used by this request, 0 is sending and 1 is downloading */ protected abstract int getQueueType(); /** * Persist message into telephony if required (i.e. when auto-persisting is on or * the calling app is non-default sms app for sending) * * @param context The context * @param result The result code of execution * @param response The response body * @return The persisted URI of the message or null if we don't persist or fail */ protected abstract Uri persistIfRequired(Context context, int result, byte[] response); /** * Prepare to make the HTTP request - will download message for sending * @return true if preparation succeeds (and request can proceed) else false */ protected abstract boolean prepareForHttpRequest(); /** * Transfer the received response to the caller * * @param fillIn the intent that will be returned to the caller * @param response the pdu to transfer * @return true if response transfer succeeds else false */ protected abstract boolean transferResponse(Intent fillIn, byte[] response); /** * Revoke the content URI permission granted by the MMS app to the phone package. * * @param context The context */ protected abstract void revokeUriPermission(Context context); } android-smsmms/src/main/java/com/android/mms/transaction/RetrieveTransaction.java +0 −5 Original line number Diff line number Diff line Loading @@ -124,11 +124,6 @@ public class RetrieveTransaction extends Transaction implements Runnable { } public void run() { // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // DownloadRequest request = new DownloadRequest(mContentLocation, mUri, null, null, null); // MmsNetworkManager manager = new MmsNetworkManager(mContext); // request.execute(mContext, manager); // } else { try { // Change the downloading state of the M-Notification.ind. DownloadManager.init(mContext.getApplicationContext()); Loading android-smsmms/src/main/java/com/android/mms/transaction/TransactionService.java +0 −27 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
android-smsmms/src/main/java/com/android/mms/service_alt/ApnSettings.javadeleted 100755 → 0 +0 −240 Original line number Diff line number Diff line /* * Copyright (C) 2015 Jacob Klinker * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.mms.service_alt; import android.content.Context; import android.content.SharedPreferences; import android.database.Cursor; import android.database.sqlite.SqliteWrapper; import android.net.NetworkUtilsHelper; import android.net.Uri; import android.preference.PreferenceManager; import android.provider.Telephony; import android.text.TextUtils; import com.android.mms.service_alt.exception.ApnException; import timber.log.Timber; import java.net.URI; import java.net.URISyntaxException; /** * APN settings used for MMS transactions */ public class ApnSettings { // MMSC URL private final String mServiceCenter; // MMSC proxy address private final String mProxyAddress; // MMSC proxy port private final int mProxyPort; // Debug text for this APN: a concatenation of interesting columns of this APN private final String mDebugText; private static final String[] APN_PROJECTION = { Telephony.Carriers.TYPE, Telephony.Carriers.MMSC, Telephony.Carriers.MMSPROXY, Telephony.Carriers.MMSPORT, Telephony.Carriers.NAME, Telephony.Carriers.APN, Telephony.Carriers.BEARER, Telephony.Carriers.PROTOCOL, Telephony.Carriers.ROAMING_PROTOCOL, Telephony.Carriers.AUTH_TYPE, Telephony.Carriers.MVNO_TYPE, Telephony.Carriers.MVNO_MATCH_DATA, Telephony.Carriers.PROXY, Telephony.Carriers.PORT, Telephony.Carriers.SERVER, Telephony.Carriers.USER, Telephony.Carriers.PASSWORD, }; private static final int COLUMN_TYPE = 0; private static final int COLUMN_MMSC = 1; private static final int COLUMN_MMSPROXY = 2; private static final int COLUMN_MMSPORT = 3; private static final int COLUMN_NAME = 4; private static final int COLUMN_APN = 5; private static final int COLUMN_BEARER = 6; private static final int COLUMN_PROTOCOL = 7; private static final int COLUMN_ROAMING_PROTOCOL = 8; private static final int COLUMN_AUTH_TYPE = 9; private static final int COLUMN_MVNO_TYPE = 10; private static final int COLUMN_MVNO_MATCH_DATA = 11; private static final int COLUMN_PROXY = 12; private static final int COLUMN_PORT = 13; private static final int COLUMN_SERVER = 14; private static final int COLUMN_USER = 15; private static final int COLUMN_PASSWORD = 16; /** * Load APN settings from system * * @param context * @param apnName the optional APN name to match */ public static ApnSettings load(Context context, String apnName, int subId) throws ApnException { SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context); String mmsc = sharedPrefs.getString("mmsc_url", ""); if (!TextUtils.isEmpty(mmsc)) { String mmsProxy = sharedPrefs.getString("mms_proxy", ""); String mmsPort = sharedPrefs.getString("mms_port", ""); return new ApnSettings(mmsc, mmsProxy, parsePort(mmsPort), "Default from settings"); } Timber.v("ApnSettings: apnName " + apnName); // TODO: CURRENT semantics is currently broken in telephony. Revive this when it is fixed. //String selection = Telephony.Carriers.CURRENT + " IS NOT NULL"; String selection = null; String[] selectionArgs = null; apnName = apnName != null ? apnName.trim() : null; if (!TextUtils.isEmpty(apnName)) { //selection += " AND " + Telephony.Carriers.APN + "=?"; selection = Telephony.Carriers.APN + "=?"; selectionArgs = new String[]{ apnName }; } Cursor cursor = null; try { cursor = SqliteWrapper.query( context, context.getContentResolver(), Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "/subId/" + subId), APN_PROJECTION, selection, selectionArgs, null/*sortOrder*/); if (cursor != null) { String mmscUrl = null; String proxyAddress = null; int proxyPort = -1; while (cursor.moveToNext()) { // Read values from APN settings if (isValidApnType( cursor.getString(COLUMN_TYPE), "mms")) { mmscUrl = trimWithNullCheck(cursor.getString(COLUMN_MMSC)); if (TextUtils.isEmpty(mmscUrl)) { continue; } mmscUrl = NetworkUtilsHelper.trimV4AddrZeros(mmscUrl); try { new URI(mmscUrl); } catch (URISyntaxException e) { throw new ApnException("Invalid MMSC url " + mmscUrl); } proxyAddress = trimWithNullCheck(cursor.getString(COLUMN_MMSPROXY)); if (!TextUtils.isEmpty(proxyAddress)) { proxyAddress = NetworkUtilsHelper.trimV4AddrZeros(proxyAddress); final String portString = trimWithNullCheck(cursor.getString(COLUMN_MMSPORT)); if (portString != null) { try { proxyPort = Integer.parseInt(portString); } catch (NumberFormatException e) { Timber.e("Invalid port " + portString); throw new ApnException("Invalid port " + portString); } } } return new ApnSettings( mmscUrl, proxyAddress, proxyPort, getDebugText(cursor)); } } } } finally { if (cursor != null) { cursor.close(); } } return new ApnSettings("", "", 80, "Failed to find APNs :("); } private static String getDebugText(Cursor cursor) { final StringBuilder sb = new StringBuilder(); sb.append("APN ["); for (int i = 0; i < cursor.getColumnCount(); i++) { final String name = cursor.getColumnName(i); final String value = cursor.getString(i); if (TextUtils.isEmpty(value)) { continue; } if (i > 0) { sb.append(' '); } sb.append(name).append('=').append(value); } sb.append("]"); return sb.toString(); } private static String trimWithNullCheck(String value) { return value != null ? value.trim() : null; } public ApnSettings(String mmscUrl, String proxyAddr, int proxyPort, String debugText) { mServiceCenter = mmscUrl; mProxyAddress = proxyAddr; mProxyPort = proxyPort; mDebugText = debugText; } public String getMmscUrl() { return mServiceCenter; } public String getProxyAddress() { return mProxyAddress; } public int getProxyPort() { return mProxyPort; } public boolean isProxySet() { return !TextUtils.isEmpty(mProxyAddress); } private static boolean isValidApnType(String types, String requestType) { // If APN type is unspecified, assume APN_TYPE_ALL. if (TextUtils.isEmpty(types)) { return true; } for (String type : types.split(",")) { type = type.trim(); if (type.equals(requestType) || type.equals("*")) { return true; } } return false; } private static int parsePort(String port) { if (TextUtils.isEmpty(port)) { return 80; } else { return Integer.parseInt(port); } } public String toString() { return mDebugText; } }
android-smsmms/src/main/java/com/android/mms/service_alt/DownloadRequest.java +0 −74 Original line number Diff line number Diff line Loading @@ -28,7 +28,6 @@ import android.os.Bundle; import android.provider.Telephony; import android.text.TextUtils; import com.android.mms.service_alt.exception.MmsHttpException; import com.google.android.mms.MmsException; import com.google.android.mms.pdu_alt.GenericPdu; import com.google.android.mms.pdu_alt.PduHeaders; Loading Loading @@ -75,44 +74,6 @@ public class DownloadRequest extends MmsRequest { mContentUri = contentUri; } @Override protected byte[] doHttp(Context context, MmsNetworkManager netMgr, ApnSettings apn) throws MmsHttpException { final MmsHttpClient mmsHttpClient = netMgr.getOrCreateHttpClient(); if (mmsHttpClient == null) { Timber.e("MMS network is not ready!"); throw new MmsHttpException(0/*statusCode*/, "MMS network is not ready"); } return mmsHttpClient.execute( mLocationUrl, null/*pud*/, MmsHttpClient.METHOD_GET, apn.isProxySet(), apn.getProxyAddress(), apn.getProxyPort(), mMmsConfig); } @Override protected PendingIntent getPendingIntent() { return mDownloadedIntent; } @Override protected int getQueueType() { return 1; } @Override protected Uri persistIfRequired(Context context, int result, byte[] response) { if (!mRequestManager.getAutoPersistingPref()) { notifyOfDownload(context); return null; } return persist(context, response, mMmsConfig, mLocationUrl, mSubId, mCreator); } public static Uri persist(Context context, byte[] response, MmsConfig.Overridden mmsConfig, String locationUrl, int subId, String creator) { // Let any mms apps running as secondary user know that a new mms has been downloaded. Loading Loading @@ -266,41 +227,6 @@ public class DownloadRequest extends MmsRequest { // } } /** * Transfer the received response to the caller (for download requests write to content uri) * * @param fillIn the intent that will be returned to the caller * @param response the pdu to transfer */ @Override protected boolean transferResponse(Intent fillIn, final byte[] response) { return mRequestManager.writePduToContentUri(mContentUri, response); } @Override protected boolean prepareForHttpRequest() { return true; } /** * Try downloading via the carrier app. * * @param context The context * @param carrierMessagingServicePackage The carrier messaging service handling the download */ public void tryDownloadingByCarrierApp(Context context, String carrierMessagingServicePackage) { // final CarrierDownloadManager carrierDownloadManger = new CarrierDownloadManager(); // final CarrierDownloadCompleteCallback downloadCallback = // new CarrierDownloadCompleteCallback(context, carrierDownloadManger); // carrierDownloadManger.downloadMms(context, carrierMessagingServicePackage, // downloadCallback); } @Override protected void revokeUriPermission(Context context) { context.revokeUriPermission(mContentUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION); } private String getContentLocation(Context context, Uri uri) throws MmsException { Cursor cursor = android.database.sqlite.SqliteWrapper.query(context, context.getContentResolver(), Loading
android-smsmms/src/main/java/com/android/mms/service_alt/MmsRequest.java +1 −276 Original line number Diff line number Diff line Loading @@ -16,32 +16,19 @@ package com.android.mms.service_alt; import android.app.Activity; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.Uri; import android.net.wifi.WifiManager; import android.os.Build; import android.os.Bundle; import android.provider.Settings; import android.service.carrier.CarrierMessagingService; import android.telephony.SmsManager; import android.telephony.TelephonyManager; import com.android.mms.service_alt.exception.ApnException; import com.android.mms.service_alt.exception.MmsHttpException; import com.klinker.android.send_message.Utils; import timber.log.Timber; /** * Base class for MMS requests. This has the common logic of sending/downloading MMS. */ public abstract class MmsRequest { private static final int RETRY_TIMES = 3; /** * Interface for certain functionalities from MmsService */ Loading Loading @@ -86,8 +73,6 @@ public abstract class MmsRequest { // MMS config overrides protected Bundle mMmsConfigOverrides; private boolean mobileDataEnabled; public MmsRequest(RequestManager requestManager, int subId, String creator, Bundle configOverrides) { mRequestManager = requestManager; Loading @@ -101,180 +86,6 @@ public abstract class MmsRequest { return mSubId; } private boolean ensureMmsConfigLoaded() { if (mMmsConfig == null) { final MmsConfig config; // Not yet retrieved from mms config manager. Try getting it. config = MmsConfigManager.getInstance().getMmsConfigBySubId(mSubId); if (config != null) { mMmsConfig = new MmsConfig.Overridden(config, mMmsConfigOverrides); } } return mMmsConfig != null; } private static boolean inAirplaneMode(final Context context) { return Settings.System.getInt(context.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0) != 0; } private static boolean isMobileDataEnabled(final Context context, final int subId) { final TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); return Utils.isDataEnabled(telephonyManager, subId); } private static boolean isDataNetworkAvailable(final Context context, final int subId) { return !inAirplaneMode(context) && isMobileDataEnabled(context, subId); } /** * Execute the request * * @param context The context * @param networkManager The network manager to use */ public void execute(Context context, MmsNetworkManager networkManager) { int result = SmsManager.MMS_ERROR_UNSPECIFIED; int httpStatusCode = 0; byte[] response = null; WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); boolean isWifiEnabled = wifi.isWifiEnabled(); if (!useWifi(context)) { wifi.setWifiEnabled(false); } mobileDataEnabled = Utils.isMobileDataEnabled(context); Timber.v("mobile data enabled: " + mobileDataEnabled); if (!mobileDataEnabled && !useWifi(context)) { Timber.v("mobile data not enabled, so forcing it to enable"); Utils.setMobileDataEnabled(context, true); } if (!ensureMmsConfigLoaded()) { // Check mms config Timber.e("MmsRequest: mms config is not loaded yet"); result = SmsManager.MMS_ERROR_CONFIGURATION_ERROR; } else if (!prepareForHttpRequest()) { // Prepare request, like reading pdu data from user Timber.e("MmsRequest: failed to prepare for request"); result = SmsManager.MMS_ERROR_IO_ERROR; } else if (!isDataNetworkAvailable(context, mSubId)) { Timber.e("MmsRequest: in airplane mode or mobile data disabled"); result = SmsManager.MMS_ERROR_NO_DATA_NETWORK; } else { // Execute long retryDelaySecs = 2; // Try multiple times of MMS HTTP request for (int i = 0; i < RETRY_TIMES; i++) { try { try { networkManager.acquireNetwork(); } catch (Exception e) { Timber.e(e, "error acquiring network"); } final String apnName = networkManager.getApnName(); try { ApnSettings apn = null; try { apn = ApnSettings.load(context, apnName, mSubId); } catch (ApnException e) { // If no APN could be found, fall back to trying without the APN name if (apnName == null) { // If the APN name was already null then don't need to retry throw (e); } Timber.i("MmsRequest: No match with APN name:" + apnName + ", try with no name"); apn = ApnSettings.load(context, null, mSubId); } Timber.i("MmsRequest: using " + apn.toString()); response = doHttp(context, networkManager, apn); result = Activity.RESULT_OK; // Success break; } finally { networkManager.releaseNetwork(); } } catch (ApnException e) { Timber.e(e, "MmsRequest: APN failure"); result = SmsManager.MMS_ERROR_INVALID_APN; break; // } catch (MmsNetworkException e) { // Timber.e(e, "MmsRequest: MMS network acquiring failure"); // result = SmsManager.MMS_ERROR_UNABLE_CONNECT_MMS; // // Retry } catch (MmsHttpException e) { Timber.e(e, "MmsRequest: HTTP or network I/O failure"); result = SmsManager.MMS_ERROR_HTTP_FAILURE; httpStatusCode = e.getStatusCode(); // Retry } catch (Exception e) { Timber.e(e, "MmsRequest: unexpected failure"); result = SmsManager.MMS_ERROR_UNSPECIFIED; break; } try { Thread.sleep(retryDelaySecs * 1000, 0/*nano*/); } catch (InterruptedException e) { } retryDelaySecs <<= 1; } } if (!mobileDataEnabled) { Timber.v("setting mobile data back to disabled"); Utils.setMobileDataEnabled(context, false); } if (!useWifi(context)) { wifi.setWifiEnabled(isWifiEnabled); } processResult(context, result, response, httpStatusCode); } /** * Process the result of the completed request, including updating the message status * in database and sending back the result via pending intents. * @param context The context * @param result The result code of execution * @param response The response body * @param httpStatusCode The optional http status code in case of http failure */ public void processResult(Context context, int result, byte[] response, int httpStatusCode) { final Uri messageUri = persistIfRequired(context, result, response); // Return MMS HTTP request result via PendingIntent final PendingIntent pendingIntent = getPendingIntent(); if (pendingIntent != null) { boolean succeeded = true; // Extra information to send back with the pending intent Intent fillIn = new Intent(); if (response != null) { succeeded = transferResponse(fillIn, response); } if (messageUri != null) { fillIn.putExtra("uri", messageUri.toString()); } if (result == SmsManager.MMS_ERROR_HTTP_FAILURE && httpStatusCode != 0) { fillIn.putExtra(SmsManager.EXTRA_MMS_HTTP_STATUS, httpStatusCode); } try { if (!succeeded) { result = SmsManager.MMS_ERROR_IO_ERROR; } pendingIntent.send(context, result, fillIn); } catch (PendingIntent.CanceledException e) { Timber.e(e, "MmsRequest: sending pending intent canceled"); } } revokeUriPermission(context); } /** * are we set up to use wifi? if so, send mms over it. */ Loading @@ -291,90 +102,4 @@ public abstract class MmsRequest { return false; } /** * Returns true if sending / downloading using the carrier app has failed and completes the * action using platform API's, otherwise false. */ protected boolean maybeFallbackToRegularDelivery(int carrierMessagingAppResult) { if (carrierMessagingAppResult == CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK || carrierMessagingAppResult == CarrierMessagingService.DOWNLOAD_STATUS_RETRY_ON_CARRIER_NETWORK) { Timber.d("Sending/downloading MMS by IP failed."); mRequestManager.addSimRequest(MmsRequest.this); return true; } else { return false; } } /** * Converts from {@code carrierMessagingAppResult} to a platform result code. */ protected static int toSmsManagerResult(int carrierMessagingAppResult) { switch (carrierMessagingAppResult) { case CarrierMessagingService.SEND_STATUS_OK: return Activity.RESULT_OK; case CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK: return SmsManager.MMS_ERROR_RETRY; default: return SmsManager.MMS_ERROR_UNSPECIFIED; } } /** * Making the HTTP request to MMSC * * @param context The context * @param netMgr The current {@link MmsNetworkManager} * @param apn The APN setting * @return The HTTP response data * @throws MmsHttpException If any network error happens */ protected abstract byte[] doHttp(Context context, MmsNetworkManager netMgr, ApnSettings apn) throws MmsHttpException; /** * @return The PendingIntent associate with the MMS sending invocation */ protected abstract PendingIntent getPendingIntent(); /** * @return The queue should be used by this request, 0 is sending and 1 is downloading */ protected abstract int getQueueType(); /** * Persist message into telephony if required (i.e. when auto-persisting is on or * the calling app is non-default sms app for sending) * * @param context The context * @param result The result code of execution * @param response The response body * @return The persisted URI of the message or null if we don't persist or fail */ protected abstract Uri persistIfRequired(Context context, int result, byte[] response); /** * Prepare to make the HTTP request - will download message for sending * @return true if preparation succeeds (and request can proceed) else false */ protected abstract boolean prepareForHttpRequest(); /** * Transfer the received response to the caller * * @param fillIn the intent that will be returned to the caller * @param response the pdu to transfer * @return true if response transfer succeeds else false */ protected abstract boolean transferResponse(Intent fillIn, byte[] response); /** * Revoke the content URI permission granted by the MMS app to the phone package. * * @param context The context */ protected abstract void revokeUriPermission(Context context); }
android-smsmms/src/main/java/com/android/mms/transaction/RetrieveTransaction.java +0 −5 Original line number Diff line number Diff line Loading @@ -124,11 +124,6 @@ public class RetrieveTransaction extends Transaction implements Runnable { } public void run() { // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // DownloadRequest request = new DownloadRequest(mContentLocation, mUri, null, null, null); // MmsNetworkManager manager = new MmsNetworkManager(mContext); // request.execute(mContext, manager); // } else { try { // Change the downloading state of the M-Notification.ind. DownloadManager.init(mContext.getApplicationContext()); Loading
android-smsmms/src/main/java/com/android/mms/transaction/TransactionService.java +0 −27 File changed.Preview size limit exceeded, changes collapsed. Show changes