Add error handling for outgoing WFC calls.

+ If POWER_OFF or OUT_OF_SERVICE is returned, show more specific
error messages based on WFC config and current wifi connectivity.

Assumes that IN_SERVICE will return if a call can be made,
regardless of the transport technology being used.

Assumes that OUT_OF_SERVICE will be returned if a call can not
be made and the radio is powered on.

Assumes that POWER_OFF will be returned if a call can not be
made and the radio is powered off.

Bug: 19167571
Change-Id: I32790bd05bb33e4890ee797f9f7a5297f6f0228c
diff --git a/src/com/android/phone/ImsUtil.java b/src/com/android/phone/ImsUtil.java
index c3d780b..868a0f1 100644
--- a/src/com/android/phone/ImsUtil.java
+++ b/src/com/android/phone/ImsUtil.java
@@ -16,9 +16,16 @@
 
 package com.android.phone;
 
+import android.content.Context;
+import android.util.Log;
+
+import com.android.ims.ImsConfig;
+import com.android.ims.ImsManager;
 import com.android.phone.PhoneGlobals;
 
 public class ImsUtil {
+    private static final String LOG_TAG = ImsUtil.class.getSimpleName();
+    private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2);
 
     private static boolean sImsPhoneSupported = false;
 
@@ -31,10 +38,32 @@
     }
 
     /**
-     * @return true if this device supports voice calls using the built-in SIP stack.
+     * @return {@code true} if this device supports voice calls using the built-in SIP stack.
      */
     static boolean isImsPhoneSupported() {
         return sImsPhoneSupported;
 
     }
+
+    /**
+     * @return {@code true} if WFC is supported by the platform and has been enabled by the user.
+     */
+    public static boolean isWfcEnabled(Context context) {
+        boolean isEnabledByPlatform = ImsManager.isWfcEnabledByPlatform(context);
+        boolean isEnabledByUser = ImsManager.isWfcEnabledByUser(context);
+        if (DBG) Log.d(LOG_TAG, "isWfcEnabled :: isEnabledByPlatform=" + isEnabledByPlatform);
+        if (DBG) Log.d(LOG_TAG, "isWfcEnabled :: isEnabledByUser=" + isEnabledByUser);
+        return isEnabledByPlatform && isEnabledByUser;
+    }
+
+    /**
+     * @return {@code true} if the device is configured to use "Wi-Fi only" mode. If WFC is not
+     * enabled, this will return {@code false}.
+     */
+    public static boolean isWfcModeWifiOnly(Context context) {
+        boolean isWifiOnlyMode =
+                ImsManager.getWfcMode(context) == ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY;
+        if (DBG) Log.d(LOG_TAG, "isWfcModeWifiOnly :: isWifiOnlyMode" + isWifiOnlyMode);
+        return isWfcEnabled(context) && isWifiOnlyMode;
+    }
 }
diff --git a/src/com/android/services/telephony/DisconnectCauseUtil.java b/src/com/android/services/telephony/DisconnectCauseUtil.java
index 0e9c0d0..aaaf7db 100644
--- a/src/com/android/services/telephony/DisconnectCauseUtil.java
+++ b/src/com/android/services/telephony/DisconnectCauseUtil.java
@@ -22,6 +22,7 @@
 
 import com.android.phone.PhoneGlobals;
 import com.android.phone.common.R;
+import com.android.phone.ImsUtil;
 
 public class DisconnectCauseUtil {
 
@@ -254,15 +255,18 @@
                 break;
 
             case android.telephony.DisconnectCause.POWER_OFF:
-                // Radio is explictly powered off, presumably because the
-                // device is in airplane mode.
-                //
-                // TODO: For now this UI is ultra-simple: we simply display
-                // a message telling the user to turn off airplane mode.
-                // But it might be nicer for the dialog to offer the option
-                // to turn the radio on right there (and automatically retry
-                // the call once network registration is complete.)
-                resourceId = R.string.incall_error_power_off;
+                // Radio is explictly powered off because the device is in airplane mode.
+
+                // TODO: Offer the option to turn the radio on, and automatically retry the call
+                // once network registration is complete.
+
+                if (ImsUtil.isWfcModeWifiOnly(context)) {
+                    resourceId = R.string.incall_error_wfc_only_no_wireless_network;
+                } else if (ImsUtil.isWfcEnabled(context)) {
+                    resourceId = R.string.incall_error_power_off_wfc;
+                } else {
+                    resourceId = R.string.incall_error_power_off;
+                }
                 break;
 
             case android.telephony.DisconnectCause.EMERGENCY_ONLY:
@@ -273,7 +277,13 @@
 
             case android.telephony.DisconnectCause.OUT_OF_SERVICE:
                 // No network connection.
-                resourceId = R.string.incall_error_out_of_service;
+                if (ImsUtil.isWfcModeWifiOnly(context)) {
+                    resourceId = R.string.incall_error_wfc_only_no_wireless_network;
+                } else if (ImsUtil.isWfcEnabled(context)) {
+                    resourceId = R.string.incall_error_out_of_service_wfc;
+                } else {
+                    resourceId = R.string.incall_error_out_of_service;
+                }
                 break;
 
             case android.telephony.DisconnectCause.NO_PHONE_NUMBER_SUPPLIED: