Merge tag 'android-security-10.0.0_r53' into int/10/fp2

Android security 10.0.0 release 53

* tag 'android-security-10.0.0_r53':

Change-Id: I6757c7953cc2a9c6b201b078916d72d621dddab8
diff --git a/src/com/android/mms/service/MmsNetworkManager.java b/src/com/android/mms/service/MmsNetworkManager.java
index 274c7c8..f7108b0 100644
--- a/src/com/android/mms/service/MmsNetworkManager.java
+++ b/src/com/android/mms/service/MmsNetworkManager.java
@@ -24,6 +24,7 @@
 import android.net.NetworkRequest;
 import android.os.Handler;
 import android.os.Looper;
+import android.provider.DeviceConfig;
 
 import com.android.mms.service.exception.MmsNetworkException;
 
@@ -31,13 +32,18 @@
  * Manages the MMS network connectivity
  */
 public class MmsNetworkManager {
-    // Timeout used to call ConnectivityManager.requestNetwork
+    private static final String MMS_SERVICE_NETWORK_REQUEST_TIMEOUT_MILLIS =
+            "mms_service_network_request_timeout_millis";
+
+    // Default timeout used to call ConnectivityManager.requestNetwork if the
+    // MMS_SERVICE_NETWORK_REQUEST_TIMEOUT_MILLIS flag is not set.
     // Given that the telephony layer will retry on failures, this timeout should be high enough.
-    private static final int NETWORK_REQUEST_TIMEOUT_MILLIS = 30 * 60 * 1000;
-    // Wait timeout for this class, a little bit longer than the above timeout
-    // to make sure we don't bail prematurely
-    private static final int NETWORK_ACQUIRE_TIMEOUT_MILLIS =
-            NETWORK_REQUEST_TIMEOUT_MILLIS + (5 * 1000);
+    private static final int DEFAULT_MMS_SERVICE_NETWORK_REQUEST_TIMEOUT_MILLIS = 30 * 60 * 1000;
+
+    // Wait timeout for this class, this is an additional delay after waiting the network request
+    // timeout to make sure we don't bail prematurely.
+    private static final int ADDITIONAL_NETWORK_ACQUIRE_TIMEOUT_MILLIS = (5 * 1000);
+
     // Waiting time used before releasing a network prematurely. This allows the MMS download
     // acknowledgement messages to be sent using the same network that was used to download the data
     private static final int NETWORK_RELEASE_TIMEOUT_MILLIS = 5 * 1000;
@@ -139,6 +145,8 @@
      * @throws com.android.mms.service.exception.MmsNetworkException if we fail to acquire it
      */
     public void acquireNetwork(final String requestId) throws MmsNetworkException {
+        int networkRequestTimeoutMillis = getNetworkRequestTimeoutMillis();
+
         synchronized (this) {
             // Since we are acquiring the network, remove the network release task if exists.
             mReleaseHandler.removeCallbacks(mNetworkReleaseTask);
@@ -151,10 +159,10 @@
             // Not available, so start a new request if not done yet
             if (mNetworkCallback == null) {
                 LogUtil.d(requestId, "MmsNetworkManager: start new network request");
-                startNewNetworkRequestLocked();
+                startNewNetworkRequestLocked(networkRequestTimeoutMillis);
             }
             try {
-                this.wait(NETWORK_ACQUIRE_TIMEOUT_MILLIS);
+                this.wait(networkRequestTimeoutMillis + ADDITIONAL_NETWORK_ACQUIRE_TIMEOUT_MILLIS);
             } catch (InterruptedException e) {
                 LogUtil.w(requestId, "MmsNetworkManager: acquire network wait interrupted");
             }
@@ -164,7 +172,11 @@
             }
 
             // Timed out
-            LogUtil.e(requestId, "MmsNetworkManager: timed out");
+            LogUtil.e(requestId,
+                    "MmsNetworkManager: timed out with networkRequestTimeoutMillis="
+                            + networkRequestTimeoutMillis
+                            + " and ADDITIONAL_NETWORK_ACQUIRE_TIMEOUT_MILLIS="
+                            + ADDITIONAL_NETWORK_ACQUIRE_TIMEOUT_MILLIS);
             if (mNetworkCallback != null) {
                 // Release the network request and wake up all the MmsRequests for fast-fail
                 // together.
@@ -177,10 +189,19 @@
         }
     }
 
+    // Timeout used to call ConnectivityManager.requestNetwork
+    // Given that the telephony layer will retry on failures, this timeout should be high enough.
+    private int getNetworkRequestTimeoutMillis() {
+        return DeviceConfig.getInt(
+                DeviceConfig.NAMESPACE_TELEPHONY, MMS_SERVICE_NETWORK_REQUEST_TIMEOUT_MILLIS,
+                DEFAULT_MMS_SERVICE_NETWORK_REQUEST_TIMEOUT_MILLIS);
+    }
+
+
     /**
      * Release the MMS network when nobody is holding on to it.
      *
-     * @param requestId request ID for logging
+     * @param requestId          request ID for logging
      * @param shouldDelayRelease whether the release should be delayed for 5 seconds, the regular
      *                           use case is to delay this for DownloadRequests to use the network
      *                           for sending an acknowledgement on the same network
@@ -208,11 +229,11 @@
     /**
      * Start a new {@link android.net.NetworkRequest} for MMS
      */
-    private void startNewNetworkRequestLocked() {
+    private void startNewNetworkRequestLocked(int networkRequestTimeoutMillis) {
         final ConnectivityManager connectivityManager = getConnectivityManager();
         mNetworkCallback = new NetworkRequestCallback();
         connectivityManager.requestNetwork(
-                mNetworkRequest, mNetworkCallback, NETWORK_REQUEST_TIMEOUT_MILLIS);
+                mNetworkRequest, mNetworkCallback, networkRequestTimeoutMillis);
     }
 
     /**
diff --git a/src/com/android/mms/service/MmsService.java b/src/com/android/mms/service/MmsService.java
index b255234..27b6b4b 100644
--- a/src/com/android/mms/service/MmsService.java
+++ b/src/com/android/mms/service/MmsService.java
@@ -192,15 +192,6 @@
                 return;
             }
 
-            // Make sure subId has MMS data
-            if (!getTelephonyManager(subId).isDataEnabledForApn(ApnSetting.TYPE_MMS)) {
-                LogUtil.w("Subscription with id: " + subId
-                        + " cannot send MMS, data connection is not available");
-                sendSettingsIntentForFailedMms(/*isIncoming=*/ false, subId);
-                sendErrorInPendingIntent(sentIntent);
-                return;
-            }
-
             final SendRequest request = new SendRequest(MmsService.this, subId, contentUri,
                     locationUrl, sentIntent, callingPkg, configOverrides, MmsService.this);
 
@@ -210,21 +201,50 @@
             if (carrierMessagingServicePackage != null) {
                 LogUtil.d(request.toString(), "sending message by carrier app");
                 request.trySendingByCarrierApp(MmsService.this, carrierMessagingServicePackage);
-            } else {
-                addSimRequest(request);
+                return;
             }
+
+            // Make sure subId has MMS data. We intentionally do this after attempting to send via a
+            // carrier messaging service as the carrier messaging service may want to handle this in
+            // a different way and may not be restricted by whether data is enabled for an APN on a
+            // given subscription.
+            if (!getTelephonyManager(subId).isDataEnabledForApn(ApnSetting.TYPE_MMS)) {
+                LogUtil.w("Subscription with id: " + subId
+                        + " cannot send MMS, data connection is not available");
+                sendSettingsIntentForFailedMms(/*isIncoming=*/ false, subId);
+                sendErrorInPendingIntent(sentIntent);
+                return;
+            }
+
+            addSimRequest(request);
         }
 
         @Override
         public void downloadMessage(int subId, String callingPkg, String locationUrl,
                 Uri contentUri, Bundle configOverrides,
                 PendingIntent downloadedIntent) {
+            // If the subId is no longer active it could be caused by an MVNO using multiple
+            // subIds, so we should try to download anyway.
+            // TODO: Fail fast when downloading will fail (i.e. SIM swapped)
             LogUtil.d("downloadMessage: " + MmsHttpClient.redactUrlForNonVerbose(locationUrl));
+
             enforceSystemUid();
 
             // Make sure the subId is correct
             subId = checkSubId(subId);
 
+            final DownloadRequest request = new DownloadRequest(MmsService.this, subId, locationUrl,
+                    contentUri, downloadedIntent, callingPkg, configOverrides, MmsService.this);
+
+            final String carrierMessagingServicePackage =
+                    getCarrierMessagingServicePackageIfExists(subId);
+
+            if (carrierMessagingServicePackage != null) {
+                LogUtil.d(request.toString(), "downloading message by carrier app");
+                request.tryDownloadingByCarrierApp(MmsService.this, carrierMessagingServicePackage);
+                return;
+            }
+
             // Make sure subId has MMS data
             if (!getTelephonyManager(subId).isDataEnabledForApn(ApnSetting.TYPE_MMS)) {
                 LogUtil.w("Subscription with id: " + subId
@@ -234,22 +254,7 @@
                 return;
             }
 
-            // If the subId is no longer active it could be caused by
-            // an MVNO using multiple subIds, so we should try to
-            // download anyway.
-            // TODO: Fail fast when downloading will fail (i.e. SIM swapped)
-
-            final DownloadRequest request = new DownloadRequest(MmsService.this, subId, locationUrl,
-                    contentUri, downloadedIntent, callingPkg, configOverrides, MmsService.this);
-            final String carrierMessagingServicePackage =
-                    getCarrierMessagingServicePackageIfExists(subId);
-
-            if (carrierMessagingServicePackage != null) {
-                LogUtil.d(request.toString(), "downloading message by carrier app");
-                request.tryDownloadingByCarrierApp(MmsService.this, carrierMessagingServicePackage);
-            } else {
-                addSimRequest(request);
-            }
+            addSimRequest(request);
         }
 
         public Bundle getCarrierConfigValues(int subId) {
@@ -715,7 +720,7 @@
                     Telephony.Threads.CONTENT_URI,
                     values,
                     ARCHIVE_CONVERSATION_SELECTION,
-                    new String[] {Long.toString(conversationId)}) != 1) {
+                    new String[]{Long.toString(conversationId)}) != 1) {
                 LogUtil.e("archiveConversation: failed to update database");
                 return false;
             }