Add FW support for CellInfo RIL commands.
Wink Saville [Tue, 9 Apr 2013 18:00:27 +0000 (11:00 -0700)]
Bug: 8235566
Change-Id: I7ad7dabc4b6c38bfba4461b08e6e30d0eb9efea1

src/java/com/android/internal/telephony/BaseCommands.java
src/java/com/android/internal/telephony/CommandsInterface.java
src/java/com/android/internal/telephony/Phone.java
src/java/com/android/internal/telephony/PhoneBase.java
src/java/com/android/internal/telephony/PhoneProxy.java
src/java/com/android/internal/telephony/RIL.java
src/java/com/android/internal/telephony/ServiceStateTracker.java
src/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
src/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
src/java/com/android/internal/telephony/sip/SipCommandInterface.java
src/java/com/android/internal/telephony/test/SimulatedCommands.java

index 8ce3873..425f89a 100644 (file)
@@ -62,6 +62,7 @@ public abstract class BaseCommands implements CommandsInterface {
     protected RegistrantList mExitEmergencyCallbackModeRegistrants = new RegistrantList();
     protected RegistrantList mRilConnectedRegistrants = new RegistrantList();
     protected RegistrantList mIccRefreshRegistrants = new RegistrantList();
+    protected RegistrantList mRilCellInfoListRegistrants = new RegistrantList();
 
     protected Registrant mGsmSmsRegistrant;
     protected Registrant mCdmaSmsRegistrant;
@@ -706,6 +707,19 @@ public abstract class BaseCommands implements CommandsInterface {
         return TelephonyManager.getLteOnCdmaModeStatic();
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void registerForCellInfoList(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+        mRilCellInfoListRegistrants.add(r);
+    }
+    @Override
+    public void unregisterForCellInfoList(Handler h) {
+        mRilCellInfoListRegistrants.remove(h);
+    }
+
     @Override
     public void testingEmergencyCall() {}
 
index 27b0d68..d4ffe20 100644 (file)
@@ -109,8 +109,6 @@ public interface CommandsInterface {
     //***** Methods
     RadioState getRadioState();
 
-    void getVoiceRadioTechnology(Message result);
-
     /**
      * Fires on any RadioState transition
      * Always fires immediately as well
@@ -1573,6 +1571,48 @@ public interface CommandsInterface {
     public void requestIsimAuthentication(String nonce, Message response);
 
     /**
+     * Get the current Voice Radio Technology.
+     *
+     * AsyncResult.result is an int array with the first value
+     * being one of the ServiceState.RIL_RADIO_TECHNOLOGY_xxx values.
+     *
+     * @param result is sent back to handler and result.obj is a AsyncResult
+     */
+    void getVoiceRadioTechnology(Message result);
+
+    /**
+     * Return the current set of CellInfo records
+     *
+     * AsyncResult.result is a of Collection<CellInfo>
+     *
+     * @param result is sent back to handler and result.obj is a AsyncResult
+     */
+    void getCellInfoList(Message result);
+
+    /**
+     * Sets the minimum time in milli-seconds between when RIL_UNSOL_CELL_INFO_LIST
+     * should be invoked.
+     *
+     * The default, 0, means invoke RIL_UNSOL_CELL_INFO_LIST when any of the reported 
+     * information changes. Setting the value to INT_MAX(0x7fffffff) means never issue
+     * A RIL_UNSOL_CELL_INFO_LIST.
+     *
+     * 
+
+     * @param rateInMillis is sent back to handler and result.obj is a AsyncResult
+     * @param response.obj is AsyncResult ar when sent to associated handler
+     *                        ar.exception carries exception on failure or null on success
+     *                        otherwise the error.
+     */
+    void setCellInfoListRate(int rateInMillis, Message response);
+
+    /**
+     * Fires when RIL_UNSOL_CELL_INFO_LIST is received from the RIL.
+     */
+    void registerForCellInfoList(Handler h, int what, Object obj);
+    void unregisterForCellInfoList(Handler h);
+
+    /**
      * Notifiy that we are testing an emergency call
      */
     public void testingEmergencyCall();
index 3e89d2f..0e9dcc1 100644 (file)
@@ -186,6 +186,18 @@ public interface Phone {
     public List<CellInfo> getAllCellInfo();
 
     /**
+     * Sets the minimum time in milli-seconds between {@link PhoneStateListener#onCellInfoChanged
+     * PhoneStateListener.onCellInfoChanged} will be invoked.
+     *
+     * The default, 0, means invoke onCellInfoChanged when any of the reported
+     * information changes. Setting the value to INT_MAX(0x7fffffff) means never issue
+     * A onCellInfoChanged.
+     *
+     * @param rateInMillis the rate
+     */
+    public void setCellInfoListRate(int rateInMillis);
+
+    /**
      * Get the current for the default apn DataState. No change notification
      * exists at this interface -- use
      * {@link android.telephony.PhoneStateListener} instead.
index 40e1db8..2cab9e5 100644 (file)
@@ -791,6 +791,14 @@ public abstract class PhoneBase extends Handler implements Phone {
         return getServiceStateTracker().getAllCellInfo();
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setCellInfoListRate(int rateInMillis) {
+        mCi.setCellInfoListRate(rateInMillis, null);
+    }
+
     @Override
     public boolean getMessageWaitingIndicator() {
         IccRecords r = mIccRecords.get();
index a88d2ec..7d36a9c 100644 (file)
@@ -272,6 +272,14 @@ public class PhoneProxy extends Handler implements Phone {
         return mActivePhone.getAllCellInfo();
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setCellInfoListRate(int rateInMillis) {
+        mActivePhone.setCellInfoListRate(rateInMillis);
+    }
+
     @Override
     public PhoneConstants.DataState getDataConnectionState() {
         return mActivePhone.getDataConnectionState(PhoneConstants.APN_TYPE_DEFAULT);
index 425da2a..b9bfc6b 100644 (file)
@@ -41,6 +41,7 @@ import android.os.Parcel;
 import android.os.PowerManager;
 import android.os.SystemProperties;
 import android.os.PowerManager.WakeLock;
+import android.telephony.CellInfo;
 import android.telephony.NeighboringCellInfo;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.Rlog;
@@ -2420,6 +2421,8 @@ public final class RIL extends BaseCommands implements CommandsInterface {
             case RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU: ret = responseVoid(p); break;
             case RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS: ret = responseICC_IO(p); break;
             case RIL_REQUEST_VOICE_RADIO_TECH: ret = responseInts(p); break;
+            case RIL_REQUEST_GET_CELL_INFO_LIST: ret = responseCellInfoList(p); break;
+            case RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE: ret = responseVoid(p); break;
             default:
                 throw new RuntimeException("Unrecognized solicited response: " + rr.mRequest);
             //break;
@@ -2601,6 +2604,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
             case RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE: ret = responseVoid(p); break;
             case RIL_UNSOL_RIL_CONNECTED: ret = responseInts(p); break;
             case RIL_UNSOL_VOICE_RADIO_TECH_CHANGED: ret =  responseInts(p); break;
+            case RIL_UNSOL_CELL_INFO_LIST: ret = responseCellInfoList(p); break;
 
             default:
                 throw new RuntimeException("Unrecognized unsol response: " + response);
@@ -2958,6 +2962,15 @@ public final class RIL extends BaseCommands implements CommandsInterface {
                 notifyRegistrantsRilConnectionChanged(((int[])ret)[0]);
                 break;
             }
+            case RIL_UNSOL_CELL_INFO_LIST: {
+                if (RILJ_LOGD) unsljLogRet(response, ret);
+
+                if (mRilCellInfoListRegistrants != null) {
+                    mRilCellInfoListRegistrants.notifyRegistrants(
+                                        new AsyncResult (null, ret, null));
+                }
+                break;
+            }
         }
     }
 
@@ -3571,6 +3584,25 @@ public final class RIL extends BaseCommands implements CommandsInterface {
         }
     }
 
+    private ArrayList<CellInfo> responseCellInfoList(Parcel p) {
+        int numberOfInfoRecs;
+        ArrayList<CellInfo> response;
+
+        /**
+         * Loop through all of the information records unmarshalling them
+         * and converting them to Java Objects.
+         */
+        numberOfInfoRecs = p.readInt();
+        response = new ArrayList<CellInfo>(numberOfInfoRecs);
+
+        for (int i = 0; i < numberOfInfoRecs; i++) {
+            CellInfo InfoRec = CellInfo.CREATOR.createFromParcel(p);
+            response.add(InfoRec);
+        }
+
+        return response;
+    }
+
     static String
     requestToString(int request) {
 /*
@@ -3687,6 +3719,8 @@ public final class RIL extends BaseCommands implements CommandsInterface {
             case RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU: return "RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU";
             case RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS: return "RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS";
             case RIL_REQUEST_VOICE_RADIO_TECH: return "RIL_REQUEST_VOICE_RADIO_TECH";
+            case RIL_REQUEST_GET_CELL_INFO_LIST: return "RIL_REQUEST_GET_CELL_INFO_LIST";
+            case RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE: return "RIL_REQUEST_SET_CELL_INFO_LIST_RATE";
             default: return "<unknown request>";
         }
     }
@@ -3736,6 +3770,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
             case RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE: return "UNSOL_EXIT_EMERGENCY_CALLBACK_MODE";
             case RIL_UNSOL_RIL_CONNECTED: return "UNSOL_RIL_CONNECTED";
             case RIL_UNSOL_VOICE_RADIO_TECH_CHANGED: return "UNSOL_VOICE_RADIO_TECH_CHANGED";
+            case RIL_UNSOL_CELL_INFO_LIST: return "UNSOL_CELL_INFO_LIST";
             default: return "<unknown reponse>";
         }
     }
@@ -3975,6 +4010,34 @@ public final class RIL extends BaseCommands implements CommandsInterface {
         send(rr);
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void getCellInfoList(Message result) {
+        RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_CELL_INFO_LIST, result);
+
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+
+        send(rr);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setCellInfoListRate(int rateInMillis, Message response) {
+        if (RILJ_LOGD) riljLog("setCellInfoListRate: " + rateInMillis);
+        RILRequest rr = RILRequest.obtain(RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE, response);
+
+        rr.mParcel.writeInt(1);
+        rr.mParcel.writeInt(rateInMillis);
+
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+
+        send(rr);
+    }
+
     /* (non-Javadoc)
      * @see com.android.internal.telephony.BaseCommands#testingEmergencyCall()
      */
index 47fb63f..dc96c6c 100644 (file)
@@ -28,6 +28,7 @@ import android.util.TimeUtils;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.ArrayList;
 import java.util.List;
 
 import com.android.internal.telephony.dataconnection.DcTrackerBase;
@@ -40,6 +41,9 @@ import com.android.internal.telephony.uicc.UiccController;
  * {@hide}
  */
 public abstract class ServiceStateTracker extends Handler {
+    protected  static final boolean DBG = true;
+    protected static final boolean VDBG = false;
+
     protected static final String PROP_FORCE_ROAMING = "telephony.test.forceRoaming";
 
     protected CommandsInterface mCi;
@@ -52,6 +56,7 @@ public abstract class ServiceStateTracker extends Handler {
     public ServiceState mSS = new ServiceState();
     protected ServiceState mNewSS = new ServiceState();
 
+    protected List<CellInfo> mLastCellInfoList = null;
     protected CellInfo mLastCellInfo = null;
 
     // This is final as subclasses alias to a more specific type
@@ -96,8 +101,6 @@ public abstract class ServiceStateTracker extends Handler {
     private boolean mPendingRadioPowerOffAfterDataOff = false;
     private int mPendingRadioPowerOffAfterDataOffTag = 0;
 
-    protected  static final boolean DBG = true;
-
     /** Signal strength poll rate. */
     protected static final int POLL_PERIOD_MILLIS = 20 * 1000;
 
@@ -146,6 +149,8 @@ public abstract class ServiceStateTracker extends Handler {
     protected static final int EVENT_CDMA_PRL_VERSION_CHANGED          = 40;
     protected static final int EVENT_RADIO_ON                          = 41;
     protected static final int EVENT_ICC_CHANGED                       = 42;
+    protected static final int EVENT_GET_CELL_INFO_LIST                = 43;
+    protected static final int EVENT_UNSOL_CELL_INFO_LIST              = 44;
 
     protected static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
 
@@ -178,6 +183,11 @@ public abstract class ServiceStateTracker extends Handler {
         "tg", // Togo
     };
 
+    private class CellInfoResult {
+        List<CellInfo> list;
+        Object lockObj = new Object();
+    }
+
     /** Reason for registration denial. */
     protected static final String REGISTRATION_DENIED_GEN  = "General";
     protected static final String REGISTRATION_DENIED_AUTH = "Authentication Failure";
@@ -189,11 +199,13 @@ public abstract class ServiceStateTracker extends Handler {
         mUiccController = UiccController.getInstance();
         mUiccController.registerForIccChanged(this, EVENT_ICC_CHANGED, null);
         mCi.setOnSignalStrengthUpdate(this, EVENT_SIGNAL_STRENGTH_UPDATE, null);
+        mCi.registerForCellInfoList(this, EVENT_UNSOL_CELL_INFO_LIST, null);
     }
 
     public void dispose() {
         mCi.unSetOnSignalStrengthUpdate(this);
         mUiccController.unregisterForIccChanged(this);
+        mCi.unregisterForCellInfoList(this);
     }
 
     public boolean getDesiredPowerState() {
@@ -341,6 +353,43 @@ public abstract class ServiceStateTracker extends Handler {
                 onUpdateIccAvailability();
                 break;
 
+            case EVENT_GET_CELL_INFO_LIST: {
+                AsyncResult ar = (AsyncResult) msg.obj;
+                CellInfoResult result = (CellInfoResult) ar.userObj;
+                synchronized(result.lockObj) {
+                    if (ar.exception != null) {
+                        log("EVENT_GET_CELL_INFO_LIST: error ret null, e=" + ar.exception);
+                        result.list = null;
+                    } else {
+                        result.list = (List<CellInfo>) ar.result;
+
+                        if (VDBG) {
+                            log("EVENT_GET_CELL_INFO_LIST: size=" + result.list.size()
+                                    + " list=" + result.list);
+                        }
+                    }
+                    mLastCellInfoList = result.list;
+                    result.lockObj.notify();
+                }
+                break;
+            }
+
+            case EVENT_UNSOL_CELL_INFO_LIST: {
+                AsyncResult ar = (AsyncResult) msg.obj;
+                if (ar.exception != null) {
+                    log("EVENT_UNSOL_CELL_INFO_LIST: error ignoring, e=" + ar.exception);
+                } else {
+                    List<CellInfo> list = (List<CellInfo>) ar.result;
+                    if (DBG) {
+                        log("EVENT_UNSOL_CELL_INFO_LIST: size=" + list.size()
+                                + " list=" + list);
+                    }
+                    mLastCellInfoList = list;
+                    mPhoneBase.notifyCellInfo(list);
+                }
+                break;
+            }
+
             default:
                 log("Unhandled message with number: " + msg.what);
                 break;
@@ -596,7 +645,38 @@ public abstract class ServiceStateTracker extends Handler {
      * @return all available cell information or null if none.
      */
     public List<CellInfo> getAllCellInfo() {
-        return null;
+        CellInfoResult result = new CellInfoResult();
+        if (VDBG) log("SST.getAllCellInfo(): E");
+        int ver = mCi.getRilVersion();
+        if (ver >= 8) {
+            if (isCallerOnDifferentThread()) {
+                Message msg = obtainMessage(EVENT_GET_CELL_INFO_LIST, result);
+                synchronized(result.lockObj) {
+                    mCi.getCellInfoList(msg);
+                    try {
+                        result.lockObj.wait();
+                    } catch (InterruptedException e) {
+                        e.printStackTrace();
+                        result.list = null;
+                    }
+                }
+            } else {
+                log("SST.getAllCellInfo(): X return last, same thread probably RadioInfo");
+                result.list = mLastCellInfoList;
+            }
+        } else {
+            log("SST.getAllCellInfo(): X not implemented");
+            result.list = null;
+        }
+        if (DBG) {
+            if (result.list != null) {
+                log("SST.getAllCellInfo(): X size=" + result.list.size()
+                        + " list=" + result.list);
+            } else {
+                log("SST.getAllCellInfo(): X size=0 list=null");
+            }
+        }
+        return result.list;
     }
 
     /**
@@ -635,4 +715,10 @@ public abstract class ServiceStateTracker extends Handler {
                     "ServiceStateTracker must be used from within one thread");
         }
     }
+
+    protected boolean isCallerOnDifferentThread() {
+        boolean value = Thread.currentThread() != getLooper().getThread();
+        if (VDBG) log("isCallerOnDifferentThread: " + value);
+        return value;
+    }
 }
index c3f3b31..74fbb61 100644 (file)
@@ -538,17 +538,23 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker {
     }
 
     /**
+     * TODO: Remove when we get new ril/modem for Galaxy Nexus.
+     *
      * @return all available cell information, the returned List maybe empty but never null.
      */
     @Override
     public List<CellInfo> getAllCellInfo() {
-        ArrayList<CellInfo> arrayList = new ArrayList<CellInfo>();
-        CellInfo ci;
-        synchronized(mCellInfo) {
-            arrayList.add(mCellInfoLte);
+        if (mCi.getRilVersion() >= 8) {
+            return super.getAllCellInfo();
+        } else {
+            ArrayList<CellInfo> arrayList = new ArrayList<CellInfo>();
+            CellInfo ci;
+            synchronized(mCellInfo) {
+                arrayList.add(mCellInfoLte);
+            }
+            if (DBG) log ("getAllCellInfo: arrayList=" + arrayList);
+            return arrayList;
         }
-        if (DBG) log ("getAllCellInfo: arrayList=" + arrayList);
-        return arrayList;
     }
 
     @Override
index b333837..9026be6 100644 (file)
@@ -1731,14 +1731,6 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
         }
     }
 
-    /**
-     * @return all available cell information or null if none.
-     */
-    @Override
-    public List<CellInfo> getAllCellInfo() {
-        return null;
-    }
-
     @Override
     protected void log(String s) {
         Rlog.d(LOG_TAG, "[CdmaSST] " + s);
index adc1378..8ed1566 100644 (file)
@@ -528,4 +528,12 @@ class SipCommandInterface extends BaseCommands implements CommandsInterface {
     @Override
     public void getVoiceRadioTechnology(Message result) {
     }
+
+    @Override
+    public void getCellInfoList(Message result) {
+    }
+
+    @Override
+    public void setCellInfoListRate(int rateInMillis, Message response) {
+    }
 }
index 23c09ee..3532670 100644 (file)
@@ -1645,4 +1645,14 @@ public final class SimulatedCommands extends BaseCommands
     public void getVoiceRadioTechnology(Message response) {
         unimplemented(response);
     }
+
+    @Override
+    public void getCellInfoList(Message response) {
+        unimplemented(response);
+    }
+
+    @Override
+    public void setCellInfoListRate(int rateInMillis, Message response) {
+        unimplemented(response);
+    }
 }