Adding EmergencyCall state to DcSwitch state machine.
Amit Mahajan [Tue, 4 Aug 2015 18:42:08 +0000 (11:42 -0700)]
State will be entered on making emergency call, and ended either on
emergency call end or emergency callback mode end if that is supported.
This is only for CDMA.

Bug: 22777920
Change-Id: I9cac544966b1b6be5410a40273d20e52cab8b396

src/java/com/android/internal/telephony/PhoneBase.java
src/java/com/android/internal/telephony/cdma/CDMAPhone.java
src/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
src/java/com/android/internal/telephony/dataconnection/DcSwitchAsyncChannel.java
src/java/com/android/internal/telephony/dataconnection/DcSwitchStateMachine.java
src/java/com/android/internal/telephony/dataconnection/DctController.java

index e4885bb..570f863 100644 (file)
@@ -335,6 +335,9 @@ public abstract class PhoneBase extends Handler implements Phone {
     protected final RegistrantList mVideoCapabilityChangedRegistrants
             = new RegistrantList();
 
+    protected final RegistrantList mEmergencyCallToggledRegistrants
+            = new RegistrantList();
+
 
     protected Looper mLooper; /* to insure registrants are in correct thread*/
 
@@ -999,6 +1002,23 @@ public abstract class PhoneBase extends Handler implements Phone {
         updateSavedNetworkOperator(nsm);
     }
 
+    /**
+     * Registration point for emergency call/callback mode start. Message.obj is AsyncResult and
+     * Message.obj.result will be Integer indicating start of call by value 1 or end of call by
+     * value 0
+     * @param h handler to notify
+     * @param what what code of message when delivered
+     * @param obj placed in Message.obj.userObj
+     */
+    public void registerForEmergencyCallToggle(Handler h, int what, Object obj) {
+        Registrant r = new Registrant(h, what, obj);
+        mEmergencyCallToggledRegistrants.add(r);
+    }
+
+    public void unregisterForEmergencyCallToggle(Handler h) {
+        mEmergencyCallToggledRegistrants.remove(h);
+    }
+
     private void updateSavedNetworkOperator(NetworkSelectMessage nsm) {
         int subId = getSubId();
         if (SubscriptionManager.isValidSubscriptionId(subId)) {
index 4248df3..ec13b15 100644 (file)
@@ -1143,9 +1143,14 @@ public class CDMAPhone extends PhoneBase {
             sendEmergencyCallbackModeChange();
             // Re-initiate data connection
             mDcTracker.setInternalDataEnabled(true);
+            notifyEmergencyCallRegistrants(false);
         }
     }
 
+    protected void notifyEmergencyCallRegistrants(boolean started) {
+        mEmergencyCallToggledRegistrants.notifyResult(started ? 1 : 0);
+    }
+
     /**
      * Handle to cancel or restart Ecm timer in emergency call back mode
      * if action is CANCEL_ECM_TIMER, cancel Ecm timer and notify apps the timer is canceled;
index e02cad7..a6e325f 100644 (file)
@@ -1122,6 +1122,7 @@ public final class CdmaCallTracker extends CallTracker {
             if (Phone.DEBUG_PHONE) log("disableDataCallInEmergencyCall");
             mIsInEmergencyCall = true;
             mPhone.mDcTracker.setInternalDataEnabled(false);
+            mPhone.notifyEmergencyCallRegistrants(true);
         }
     }
 
@@ -1139,6 +1140,7 @@ public final class CdmaCallTracker extends CallTracker {
             if (inEcm.compareTo("false") == 0) {
                 // Re-initiate data connection
                 mPhone.mDcTracker.setInternalDataEnabled(true);
+                mPhone.notifyEmergencyCallRegistrants(false);
             }
         }
     }
index f56570f..ca4656c 100644 (file)
@@ -44,8 +44,10 @@ public class DcSwitchAsyncChannel extends AsyncChannel {
     static final int RSP_IS_IDLE_OR_DETACHING_STATE = BASE + 6;
     static final int EVENT_DATA_ATTACHED =            BASE + 7;
     static final int EVENT_DATA_DETACHED =            BASE + 8;
+    static final int EVENT_EMERGENCY_CALL_STARTED =   BASE + 9;
+    static final int EVENT_EMERGENCY_CALL_ENDED =     BASE + 10;
 
-    private static final int CMD_TO_STRING_COUNT = EVENT_DATA_DETACHED - BASE + 1;
+    private static final int CMD_TO_STRING_COUNT = EVENT_EMERGENCY_CALL_ENDED - BASE + 1;
     private static String[] sCmdToString = new String[CMD_TO_STRING_COUNT];
     static {
         sCmdToString[REQ_CONNECT - BASE] = "REQ_CONNECT";
@@ -57,6 +59,8 @@ public class DcSwitchAsyncChannel extends AsyncChannel {
         sCmdToString[RSP_IS_IDLE_OR_DETACHING_STATE - BASE] = "RSP_IS_IDLE_OR_DETACHING_STATE";
         sCmdToString[EVENT_DATA_ATTACHED - BASE] = "EVENT_DATA_ATTACHED";
         sCmdToString[EVENT_DATA_DETACHED - BASE] = "EVENT_DATA_DETACHED";
+        sCmdToString[EVENT_EMERGENCY_CALL_STARTED - BASE] = "EVENT_EMERGENCY_CALL_STARTED";
+        sCmdToString[EVENT_EMERGENCY_CALL_ENDED - BASE] = "EVENT_EMERGENCY_CALL_ENDED";
     }
 
     public static class RequestInfo {
@@ -117,12 +121,18 @@ public class DcSwitchAsyncChannel extends AsyncChannel {
 
     public void notifyDataAttached() {
         sendMessage(EVENT_DATA_ATTACHED);
-        if (DBG) log("notifyDataAttached");
     }
 
     public void notifyDataDetached() {
         sendMessage(EVENT_DATA_DETACHED);
-        if (DBG) log("EVENT_DATA_DETACHED");
+    }
+
+    public void notifyEmergencyCallToggled(int start) {
+        if (start != 0) {
+            sendMessage(EVENT_EMERGENCY_CALL_STARTED);
+        } else {
+            sendMessage(EVENT_EMERGENCY_CALL_ENDED);
+        }
     }
 
     private boolean rspIsIdle(Message response) {
index ddde51b..c11cd5b 100644 (file)
@@ -17,6 +17,7 @@
 package com.android.internal.telephony.dataconnection;
 
 import com.android.internal.util.AsyncChannel;
+import com.android.internal.util.IState;
 import com.android.internal.util.Protocol;
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;
@@ -48,11 +49,16 @@ public class DcSwitchStateMachine extends StateMachine {
     private AsyncChannel mAc;
 
     private IdleState mIdleState = new IdleState();
+    private EmergencyState mEmergencyState = new EmergencyState();
     private AttachingState mAttachingState = new AttachingState();
     private AttachedState mAttachedState = new AttachedState();
     private DetachingState mDetachingState = new DetachingState();
     private DefaultState mDefaultState = new DefaultState();
 
+    // In case of transition to emergency state, this tracks the state of the state machine prior
+    // to entering emergency state
+    private IState mPreEmergencyState;
+
     protected DcSwitchStateMachine(Phone phone, String name, int id) {
         super(name);
         if (DBG) log("DcSwitchState constructor E");
@@ -61,6 +67,7 @@ public class DcSwitchStateMachine extends StateMachine {
 
         addState(mDefaultState);
         addState(mIdleState, mDefaultState);
+        addState(mEmergencyState, mDefaultState);
         addState(mAttachingState, mDefaultState);
         addState(mAttachedState, mDefaultState);
         addState(mDetachingState, mDefaultState);
@@ -140,6 +147,40 @@ public class DcSwitchStateMachine extends StateMachine {
         }
     }
 
+    private class EmergencyState extends State {
+        @Override
+        public boolean processMessage(Message msg) {
+            final PhoneBase pb = (PhoneBase)((PhoneProxy)mPhone).getActivePhone();
+            if (!pb.mDcTracker.isEmergency()) {
+                loge("EmergencyState: isEmergency() is false. deferMessage msg.what=0x" +
+                        Integer.toHexString(msg.what));
+                deferMessage(msg);
+                transitionTo(mPreEmergencyState);
+                return HANDLED;
+            }
+
+            switch (msg.what) {
+                case DcSwitchAsyncChannel.EVENT_EMERGENCY_CALL_ENDED: {
+                    transitionTo(mPreEmergencyState);
+                    break;
+                }
+
+                case DcSwitchAsyncChannel.EVENT_EMERGENCY_CALL_STARTED: {
+                    loge("EmergencyState: ignoring EVENT_EMERGENCY_CALL_STARTED");
+                    break;
+                }
+
+                default: {
+                    log("EmergencyState: deferMessage msg.what=0x" + Integer.toHexString(msg.what));
+                    deferMessage(msg);
+                    break;
+                }
+            }
+
+            return HANDLED;
+        }
+    }
+
     private class AttachingState extends State {
         private int mCurrentAllowedSequence = 0;
         @Override
@@ -398,6 +439,11 @@ public class DcSwitchStateMachine extends StateMachine {
                             DcSwitchAsyncChannel.RSP_IS_IDLE_OR_DETACHING_STATE, val ? 1 : 0);
                     break;
                 }
+                case DcSwitchAsyncChannel.EVENT_EMERGENCY_CALL_STARTED: {
+                    mPreEmergencyState = getCurrentState();
+                    transitionTo(mEmergencyState);
+                    break;
+                }
                 default:
                     if (DBG) {
                         log("DefaultState: shouldn't happen but ignore msg.what=0x" +
index ce7bae9..8211d78 100644 (file)
@@ -22,6 +22,7 @@ import android.net.ConnectivityManager;
 import android.net.NetworkCapabilities;
 import android.net.NetworkFactory;
 import android.net.NetworkRequest;
+import android.os.AsyncResult;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -62,6 +63,7 @@ public class DctController extends Handler {
 
     private static final int EVENT_DATA_ATTACHED = 500;
     private static final int EVENT_DATA_DETACHED = 600;
+    private static final int EVENT_EMERGENCY_CALL_TOGGLED = 700;
 
     private static DctController sDctController;
 
@@ -126,6 +128,8 @@ public class DctController extends Handler {
                    EVENT_DATA_ATTACHED + index, null);
         phoneBase.getServiceStateTracker().registerForDataConnectionDetached(mRspHandler,
                    EVENT_DATA_DETACHED + index, null);
+        phoneBase.registerForEmergencyCallToggle(mRspHandler,
+                EVENT_EMERGENCY_CALL_TOGGLED + index, null);
 
         ConnectivityManager cm = (ConnectivityManager)mPhones[index].getContext()
             .getSystemService(Context.CONNECTIVITY_SERVICE);
@@ -164,7 +168,14 @@ public class DctController extends Handler {
     private Handler mRspHandler = new Handler() {
         @Override
         public void handleMessage(Message msg){
-            if (msg.what >= EVENT_DATA_DETACHED) {
+            if (msg.what >= EVENT_EMERGENCY_CALL_TOGGLED) {
+                logd("EVENT_PHONE" + (msg.what - EVENT_EMERGENCY_CALL_TOGGLED + 1)
+                        + "_EMERGENCY_CALL_END.");
+                AsyncResult ar = (AsyncResult) msg.obj;
+                Integer toggle = (Integer) ar.result;
+                mDcSwitchAsyncChannel[msg.what - EVENT_EMERGENCY_CALL_TOGGLED].
+                        notifyEmergencyCallToggled(toggle.intValue());
+            } else if (msg.what >= EVENT_DATA_DETACHED) {
                 logd("EVENT_PHONE" + (msg.what - EVENT_DATA_DETACHED + 1)
                         + "_DATA_DETACH.");
                 mDcSwitchAsyncChannel[msg.what - EVENT_DATA_DETACHED].notifyDataDetached();