DO NOT MERGE - Merge Android R QPR1

Bug: 172690556
Merged-In: I4e02ba38f70d8358ae2e70a9920320e4b09f3d61
Change-Id: Id0fe95b3444297fb120155c4e27d76f02870b2fb
diff --git a/src/com/android/mms/service/ApnSettings.java b/src/com/android/mms/service/ApnSettings.java
index 7e4a0fc..65d38b7 100644
--- a/src/com/android/mms/service/ApnSettings.java
+++ b/src/com/android/mms/service/ApnSettings.java
@@ -102,7 +102,7 @@
         }
 
         try (Cursor cursor = context.getContentResolver().query(
-                    Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "/subId/" + subId),
+                    Uri.withAppendedPath(Telephony.Carriers.SIM_APN_URI, String.valueOf(subId)),
                     APN_PROJECTION,
                     selection,
                     selectionArgs,
diff --git a/src/com/android/mms/service/MmsRequest.java b/src/com/android/mms/service/MmsRequest.java
index 15c80db..de24a49 100644
--- a/src/com/android/mms/service/MmsRequest.java
+++ b/src/com/android/mms/service/MmsRequest.java
@@ -21,9 +21,15 @@
 import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
 import android.os.Bundle;
 import android.service.carrier.CarrierMessagingService;
 import android.service.carrier.CarrierMessagingServiceWrapper.CarrierMessagingCallback;
+import android.telephony.AnomalyReporter;
+import android.telephony.ims.feature.MmTelFeature;
+import android.telephony.ims.ImsMmTelManager;
+import android.telephony.ims.stub.ImsRegistrationImplBase;
 import android.telephony.SmsManager;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
@@ -32,11 +38,17 @@
 import com.android.mms.service.exception.MmsHttpException;
 import com.android.mms.service.exception.MmsNetworkException;
 
+import java.util.UUID;
+
 /**
  * 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;
+    // Signal level threshold for both wifi and cellular
+    private static final int SIGNAL_LEVEL_THRESHOLD = 2;
+    // MMS anomaly uuid
+    private final UUID mAnomalyUUID = UUID.fromString("e4330975-17be-43b7-87d6-d9f281d33278");
 
     /**
      * Interface for certain functionalities from MmsService
@@ -246,6 +258,7 @@
                 if (!succeeded) {
                     result = SmsManager.MMS_ERROR_IO_ERROR;
                 }
+                reportPossibleAnomaly(result, httpStatusCode);
                 pendingIntent.send(context, result, fillIn);
             } catch (PendingIntent.CanceledException e) {
                 LogUtil.e(requestId, "Sending pending intent canceled", e);
@@ -255,6 +268,80 @@
         revokeUriPermission(context);
     }
 
+    private void reportPossibleAnomaly(int result, int httpStatusCode) {
+        switch (result) {
+            case SmsManager.MMS_ERROR_HTTP_FAILURE:
+                if (isPoorSignal()) {
+                    LogUtil.i(this.toString(), "Poor Signal");
+                    break;
+                }
+            case SmsManager.MMS_ERROR_INVALID_APN:
+            case SmsManager.MMS_ERROR_UNABLE_CONNECT_MMS:
+            case SmsManager.MMS_ERROR_UNSPECIFIED:
+            case SmsManager.MMS_ERROR_IO_ERROR:
+                String message = "MMS failed";
+                LogUtil.i(this.toString(),
+                        message + " with error: " + result + " httpStatus:" + httpStatusCode);
+                AnomalyReporter.reportAnomaly(generateUUID(result, httpStatusCode), message);
+                break;
+            default:
+                break;
+        }
+    }
+
+    private UUID generateUUID(int result, int httpStatusCode) {
+        long lresult = result;
+        long lhttpStatusCode = httpStatusCode;
+        return new UUID(mAnomalyUUID.getMostSignificantBits(),
+                mAnomalyUUID.getLeastSignificantBits() + ((lhttpStatusCode << 32) + lresult));
+    }
+
+    private boolean isPoorSignal() {
+        // Check Wifi signal strength when IMS registers via Wifi
+        if (isImsOnWifi()) {
+            int rssi = 0;
+            WifiManager wifiManager = mContext.getSystemService(WifiManager.class);
+            final WifiInfo wifiInfo = wifiManager.getConnectionInfo();
+            if (wifiInfo != null) {
+                rssi = wifiInfo.getRssi();
+            } else {
+                return false;
+            }
+            final int wifiLevel = wifiManager.calculateSignalLevel(rssi);
+            LogUtil.d(this.toString(), "Wifi signal rssi: " + rssi + " level:" + wifiLevel);
+            if (wifiLevel <= SIGNAL_LEVEL_THRESHOLD) {
+                return true;
+            }
+            return false;
+        } else {
+            // Check cellular signal strength
+            final TelephonyManager telephonyManager = mContext.getSystemService(
+                    TelephonyManager.class).createForSubscriptionId(mSubId);
+            final int cellLevel = telephonyManager.getSignalStrength().getLevel();
+            LogUtil.d(this.toString(), "Cellular signal level:" + cellLevel);
+            if (cellLevel <= SIGNAL_LEVEL_THRESHOLD) {
+                return true;
+            }
+            return false;
+        }
+    }
+
+    private boolean isImsOnWifi() {
+        ImsMmTelManager imsManager;
+        try {
+            imsManager = ImsMmTelManager.createForSubscriptionId(mSubId);
+        } catch (IllegalArgumentException e) {
+            LogUtil.e(this.toString(), "invalid subid:" + mSubId);
+            return false;
+        }
+        if (imsManager != null) {
+            return imsManager.isAvailable(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
+                    ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN);
+        } else {
+            return false;
+        }
+    }
+
     /**
      * Returns true if sending / downloading using the carrier app has failed and completes the
      * action using platform API's, otherwise false.