Merge change 27106 into eclair

* changes:
  Use reflection to figure out a readable string from install error code.
diff --git a/api/current.xml b/api/current.xml
index d5f3f46..37fb3a8 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -122805,7 +122805,7 @@
  type="android.telephony.NeighboringCellInfo"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </constructor>
@@ -122813,7 +122813,7 @@
  type="android.telephony.NeighboringCellInfo"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="rssi" type="int">
@@ -122853,6 +122853,39 @@
  visibility="public"
 >
 </method>
+<method name="getLac"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getNetworkType"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getPsc"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getRssi"
  return="int"
  abstract="false"
@@ -122871,7 +122904,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="cid" type="int">
@@ -122884,7 +122917,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="rssi" type="int">
diff --git a/core/java/android/pim/vcard/VCardComposer.java b/core/java/android/pim/vcard/VCardComposer.java
index 2404a43..e01bd3c 100644
--- a/core/java/android/pim/vcard/VCardComposer.java
+++ b/core/java/android/pim/vcard/VCardComposer.java
@@ -29,9 +29,9 @@
 import android.provider.ContactsContract.Contacts;
 import android.provider.ContactsContract.Data;
 import android.provider.ContactsContract.RawContacts;
+import android.provider.ContactsContract.CommonDataKinds.Birthday;
 import android.provider.ContactsContract.CommonDataKinds.Email;
 import android.provider.ContactsContract.CommonDataKinds.Im;
-import android.provider.ContactsContract.CommonDataKinds.Birthday;
 import android.provider.ContactsContract.CommonDataKinds.Nickname;
 import android.provider.ContactsContract.CommonDataKinds.Note;
 import android.provider.ContactsContract.CommonDataKinds.Organization;
@@ -40,9 +40,6 @@
 import android.provider.ContactsContract.CommonDataKinds.StructuredName;
 import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
 import android.provider.ContactsContract.CommonDataKinds.Website;
-import android.provider.CallLog.Calls;
-import android.provider.CallLog;
-import android.text.format.Time;
 import android.text.TextUtils;
 import android.text.format.Time;
 import android.util.CharsetUtils;
@@ -86,6 +83,17 @@
 
     private final static String DEFAULT_EMAIL_TYPE = Constants.ATTR_TYPE_INTERNET;
 
+    public static final String FAILURE_REASON_FAILED_TO_GET_DATABASE_INFO =
+        "Failed to get database information";
+
+    public static final String FAILURE_REASON_NO_ENTRY =
+        "There's no exportable in the database";
+
+    public static final String FAILURE_REASON_NOT_INITIALIZED =
+        "The vCard composer object is not correctly initialized";
+
+    public static final String NO_ERROR = "No error";
+
     public static interface OneEntryHandler {
         public boolean onInit(Context context);
 
@@ -276,7 +284,7 @@
     private boolean mTerminateIsCalled;
     private List<OneEntryHandler> mHandlerList;
 
-    private String mErrorReason = "No error";
+    private String mErrorReason = NO_ERROR;
 
     private static final Map<Integer, String> sImMap;
 
@@ -293,12 +301,12 @@
 
     private boolean mIsCallLogComposer = false;
 
-    private static final String[] CONTACTS_PROJECTION = new String[] {
-        Contacts._ID,
+    private static final String[] sRawContactsProjection = new String[] {
+        RawContacts._ID,
     };
 
     /** The projection to use when querying the call log table */
-    private static final String[] CALL_LOG_PROJECTION = new String[] {
+    private static final String[] sCallLogProjection = new String[] {
             Calls.NUMBER, Calls.DATE, Calls.TYPE, Calls.CACHED_NAME, Calls.CACHED_NUMBER_TYPE,
             Calls.CACHED_NUMBER_LABEL
     };
@@ -312,17 +320,23 @@
     private static final String FLAG_TIMEZONE_UTC = "Z";
 
     public VCardComposer(Context context) {
-        this(context, VCardConfig.VCARD_TYPE_DEFAULT, true);
+        this(context, VCardConfig.VCARD_TYPE_DEFAULT, true, false);
     }
 
     public VCardComposer(Context context, String vcardTypeStr,
             boolean careHandlerErrors) {
         this(context, VCardConfig.getVCardTypeFromString(vcardTypeStr),
-                careHandlerErrors);
+                careHandlerErrors, false);
+    }
+
+    public VCardComposer(Context context, int vcardType, boolean careHandlerErrors) {
+        this(context, vcardType, careHandlerErrors, false);
     }
 
     /**
-     * Construct for supporting call log entry vCard composing
+     * Construct for supporting call log entry vCard composing.
+     *
+     * @param isCallLogComposer true if this composer is for creating Call Log vCard.
      */
     public VCardComposer(Context context, int vcardType, boolean careHandlerErrors,
             boolean isCallLogComposer) {
@@ -359,10 +373,6 @@
         }
     }
 
-    public VCardComposer(Context context, int vcardType, boolean careHandlerErrors) {
-        this(context, vcardType, careHandlerErrors, false);
-    }
-
     /**
      * This static function is to compose vCard for phone own number
      */
@@ -429,25 +439,27 @@
         }
 
         if (mIsCallLogComposer) {
-            mCursor = mContentResolver.query(CallLog.Calls.CONTENT_URI, CALL_LOG_PROJECTION,
+            mCursor = mContentResolver.query(CallLog.Calls.CONTENT_URI, sCallLogProjection,
                     selection, selectionArgs, null);
         } else {
-            // TODO: thorow an appropriate exception!
-            mCursor = mContentResolver.query(RawContacts.CONTENT_URI, CONTACTS_PROJECTION,
+            mCursor = mContentResolver.query(RawContacts.CONTENT_URI, sRawContactsProjection,
                     selection, selectionArgs, null);
         }
 
-        if (mCursor == null || !mCursor.moveToFirst()) {
-            if (mCursor != null) {
-                try {
-                    mCursor.close();
-                } catch (SQLiteException e) {
-                    Log.e(LOG_TAG, "SQLiteException on Cursor#close(): "
-                            + e.getMessage());
-                }
+        if (mCursor == null) {
+            mErrorReason = FAILURE_REASON_FAILED_TO_GET_DATABASE_INFO;
+            return false;
+        }
+
+        if (mCursor.getCount() == 0 || !mCursor.moveToFirst()) {
+            try {
+                mCursor.close();
+            } catch (SQLiteException e) {
+                Log.e(LOG_TAG, "SQLiteException on Cursor#close(): " + e.getMessage());
+            } finally {
                 mCursor = null;
+                mErrorReason = FAILURE_REASON_NO_ENTRY;
             }
-            mErrorReason = "Getting database information failed.";
             return false;
         }
 
@@ -462,8 +474,7 @@
 
     public boolean createOneEntry() {
         if (mCursor == null || mCursor.isAfterLast()) {
-            // TODO: ditto
-            mErrorReason = "Not initialized or database has some problem.";
+            mErrorReason = FAILURE_REASON_NOT_INITIALIZED;
             return false;
         }
         String name = null;
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 6ac1f07..3ce1815 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -356,7 +356,10 @@
     // Whether to prevent drag during touch. The initial value depends on
     // mForwardTouchEvents. If WebCore wants touch events, we assume it will
     // take control of touch events unless it says no for touch down event.
-    private boolean mPreventDrag;
+    private static final int PREVENT_DRAG_NO = 0;
+    private static final int PREVENT_DRAG_MAYBE_YES = 1;
+    private static final int PREVENT_DRAG_YES = 2;
+    private int mPreventDrag = PREVENT_DRAG_NO;
 
     // To keep track of whether the current drag was initiated by a WebTextView,
     // so that we know not to hide the cursor
@@ -3710,7 +3713,8 @@
                     }
                 } else {
                     mTouchMode = TOUCH_INIT_MODE;
-                    mPreventDrag = mForwardTouchEvents;
+                    mPreventDrag = mForwardTouchEvents ? PREVENT_DRAG_MAYBE_YES
+                            : PREVENT_DRAG_NO;
                     mWebViewCore.sendMessage(
                             EventHub.UPDATE_FRAME_CACHE_IF_LOADING);
                     if (mLogEvent && eventTime - mLastTouchUpTime < 1000) {
@@ -3751,11 +3755,15 @@
                         invalidate();
                         break;
                     }
-                    if (mPreventDrag || (deltaX * deltaX + deltaY * deltaY)
-                            < mTouchSlopSquare) {
+                    if ((deltaX * deltaX + deltaY * deltaY) < mTouchSlopSquare) {
                         break;
                     }
-
+                    if (mPreventDrag == PREVENT_DRAG_MAYBE_YES) {
+                        // track mLastTouchTime as we may need to do fling at
+                        // ACTION_UP
+                        mLastTouchTime = eventTime;
+                        break;
+                    }
                     if (mTouchMode == TOUCH_SHORTPRESS_MODE
                             || mTouchMode == TOUCH_SHORTPRESS_START_MODE) {
                         mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
@@ -3884,15 +3892,6 @@
                         mTouchMode = TOUCH_DONE_MODE;
                         doDoubleTap();
                         break;
-                    case TOUCH_INIT_MODE: // tap
-                        mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
-                        if (!mPreventDrag) {
-                            mPrivateHandler.sendMessageDelayed(
-                                    mPrivateHandler.obtainMessage(
-                                    RELEASE_SINGLE_TAP),
-                                    ViewConfiguration.getDoubleTapTimeout());
-                        }
-                        break;
                     case TOUCH_SHORTPRESS_START_MODE:
                     case TOUCH_SHORTPRESS_MODE:
                         mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
@@ -3904,6 +3903,34 @@
                         commitCopy();
                         mTouchSelection = false;
                         break;
+                    case TOUCH_INIT_MODE: // tap
+                        mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
+                        if ((deltaX * deltaX + deltaY * deltaY) > mTouchSlopSquare) {
+                            Log.w(LOGTAG, "Miss a drag as we are waiting for" +
+                                    " WebCore's response for touch down.");
+                            if (computeHorizontalScrollExtent() < computeHorizontalScrollRange()
+                                    || computeVerticalScrollExtent() < computeVerticalScrollRange()) {
+                                // we will not rewrite drag code here, but we
+                                // will try fling if it applies.
+                                WebViewCore.pauseUpdate(mWebViewCore);
+                                // fall through to TOUCH_DRAG_MODE
+                            } else {
+                                break;
+                            }
+                        } else {
+                            if (mPreventDrag == PREVENT_DRAG_MAYBE_YES) {
+                                // if mPreventDrag is not confirmed, treat it as
+                                // no so that it won't block tap or double tap.
+                                mPreventDrag = PREVENT_DRAG_NO;
+                            }
+                            if (mPreventDrag == PREVENT_DRAG_NO) {
+                                mPrivateHandler.sendMessageDelayed(
+                                        mPrivateHandler.obtainMessage(
+                                        RELEASE_SINGLE_TAP),
+                                        ViewConfiguration.getDoubleTapTimeout());
+                            }
+                            break;
+                        }
                     case TOUCH_DRAG_MODE:
                         // redraw in high-quality, as we're done dragging
                         invalidate();
@@ -4821,6 +4848,11 @@
                     break;
                 }
                 case SWITCH_TO_SHORTPRESS: {
+                    // if mPreventDrag is not confirmed, treat it as no so that
+                    // it won't block panning the page.
+                    if (mPreventDrag == PREVENT_DRAG_MAYBE_YES) {
+                        mPreventDrag = PREVENT_DRAG_NO;
+                    }
                     if (mTouchMode == TOUCH_INIT_MODE) {
                         mTouchMode = TOUCH_SHORTPRESS_START_MODE;
                         updateSelection();
@@ -4830,7 +4862,7 @@
                     break;
                 }
                 case SWITCH_TO_LONGPRESS: {
-                    if (!mPreventDrag) {
+                    if (mPreventDrag == PREVENT_DRAG_NO) {
                         mTouchMode = TOUCH_DONE_MODE;
                         performLongClick();
                         rebuildWebTextView();
@@ -4838,7 +4870,7 @@
                     break;
                 }
                 case RELEASE_SINGLE_TAP: {
-                    if (!mPreventDrag) {
+                    if (mPreventDrag == PREVENT_DRAG_NO) {
                         mTouchMode = TOUCH_DONE_MODE;
                         doShortPress();
                     }
@@ -5064,9 +5096,14 @@
 
                 case PREVENT_TOUCH_ID:
                     if (msg.arg1 == MotionEvent.ACTION_DOWN) {
-                        mPreventDrag = msg.arg2 == 1;
-                        if (mPreventDrag) {
-                            mTouchMode = TOUCH_DONE_MODE;
+                        // dont override if mPreventDrag has been set to no due
+                        // to time out
+                        if (mPreventDrag == PREVENT_DRAG_MAYBE_YES) {
+                            mPreventDrag = msg.arg2 == 1 ? PREVENT_DRAG_YES
+                                    : PREVENT_DRAG_NO;
+                            if (mPreventDrag == PREVENT_DRAG_YES) {
+                                mTouchMode = TOUCH_DONE_MODE;
+                            }
                         }
                     }
                     break;
diff --git a/core/res/res/drawable-hdpi/gallery_unselected_default.9.png b/core/res/res/drawable-hdpi/gallery_unselected_default.9.png
index 855dca1..3d10b86 100644
--- a/core/res/res/drawable-hdpi/gallery_unselected_default.9.png
+++ b/core/res/res/drawable-hdpi/gallery_unselected_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/gallery_unselected_pressed.9.png b/core/res/res/drawable-hdpi/gallery_unselected_pressed.9.png
index 5ec400c..2fa7c46 100644
--- a/core/res/res/drawable-hdpi/gallery_unselected_pressed.9.png
+++ b/core/res/res/drawable-hdpi/gallery_unselected_pressed.9.png
Binary files differ
diff --git a/telephony/java/android/telephony/NeighboringCellInfo.java b/telephony/java/android/telephony/NeighboringCellInfo.java
index f492abd..d698169 100644
--- a/telephony/java/android/telephony/NeighboringCellInfo.java
+++ b/telephony/java/android/telephony/NeighboringCellInfo.java
@@ -18,6 +18,15 @@
 
 import android.os.Parcel;
 import android.os.Parcelable;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_EDGE;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_GPRS;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_UMTS;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_HSDPA;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_HSUPA;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_HSPA;
+
+
 
 /**
  * Represents the neighboring cell information, including
@@ -34,19 +43,53 @@
      */
     static final public int UNKNOWN_CID = -1;
 
+    /**
+     * In GSM, mRssi is the Received RSSI;
+     * In UMTS, mRssi is the Level index of CPICH Received Signal Code Power
+     */
     private int mRssi;
+    /**
+     * CID in 16 bits format in GSM. Return UNKNOWN_CID in UMTS and CMDA.
+     */
     private int mCid;
+    /**
+     * LAC in 16 bits format in GSM. Return UNKNOWN_CID in UMTS and CMDA.
+     */
+    private int mLac;
+    /**
+     * Primary Scrambling Code in 9 bits format in UMTS
+     * Return UNKNOWN_CID in GSM and CMDA.
+     */
+    private int mPsc;
+    /**
+     * Radio network type, value is one of following
+     * TelephonyManager.NETWORK_TYPE_XXXXXX.
+     */
+    private int mNetworkType;
 
     /**
+     * @deprecated
      * Empty constructor.  Initializes the RSSI and CID.
+     *
+     * NeighboringCellInfo is one time shot for the neighboring cells based on
+     * the radio network type at that moment. Its constructor needs radio network
+     * type.
      */
     public NeighboringCellInfo() {
         mRssi = UNKNOWN_RSSI;
+        mLac = UNKNOWN_CID;
         mCid = UNKNOWN_CID;
+        mPsc = UNKNOWN_CID;
+        mNetworkType = NETWORK_TYPE_UNKNOWN;
     }
 
     /**
+     * @deprecated
      * Initialize the object from rssi and cid.
+     *
+     * NeighboringCellInfo is one time shot for the neighboring cells based on
+     * the radio network type at that moment. Its constructor needs radio network
+     * type.
      */
     public NeighboringCellInfo(int rssi, int cid) {
         mRssi = rssi;
@@ -54,40 +97,148 @@
     }
 
     /**
+     * @hide
+     * Initialize the object from rssi, location string, and radioType
+     * radioType is one of following
+     * {@link TelephonyManager#NETWORK_TYPE_GPRS TelephonyManager.NETWORK_TYPE_GPRS},
+     * {@link TelephonyManager#NETWORK_TYPE_EDGE TelephonyManager.NETWORK_TYPE_EDGE},
+     * {@link TelephonyManager#NETWORK_TYPE_UMTS TelephonyManager.NETWORK_TYPE_UMTS},
+     * {@link TelephonyManager#NETWORK_TYPE_HSDPA TelephonyManager.NETWORK_TYPE_HSDPA},
+     * {@link TelephonyManager#NETWORK_TYPE_HSUPA TelephonyManager.NETWORK_TYPE_HSUPA},
+     * and {@link TelephonyManager#NETWORK_TYPE_HSPA TelephonyManager.NETWORK_TYPE_HSPA}.
+     */
+    public NeighboringCellInfo(int rssi, String location, int radioType) {
+        // set default value
+        mRssi = rssi;
+        mNetworkType = NETWORK_TYPE_UNKNOWN;
+        mPsc = UNKNOWN_CID;
+        mLac = UNKNOWN_CID;
+        mCid = UNKNOWN_CID;
+
+
+        // pad location string with leading "0"
+        int l = location.length();
+        if (l > 8) return;
+        if (l < 8) {
+            for (int i = 0; i < (8-l); i++) {
+                location = "0" + location;
+            }
+        }
+
+        try {// set LAC/CID or PSC based on radioType
+            switch (radioType) {
+            case NETWORK_TYPE_GPRS:
+            case NETWORK_TYPE_EDGE:
+                mNetworkType = radioType;
+                mLac = Integer.valueOf(location.substring(0, 4), 16);
+                mCid = Integer.valueOf(location.substring(4), 16);
+                break;
+            case NETWORK_TYPE_UMTS:
+            case NETWORK_TYPE_HSDPA:
+            case NETWORK_TYPE_HSUPA:
+            case NETWORK_TYPE_HSPA:
+                mNetworkType = radioType;
+                mPsc = Integer.valueOf(location, 16);
+                break;
+            }
+        } catch (NumberFormatException e) {
+            // parsing location error
+            mPsc = UNKNOWN_CID;
+            mLac = UNKNOWN_CID;
+            mCid = UNKNOWN_CID;
+            mNetworkType = NETWORK_TYPE_UNKNOWN;
+        }
+    }
+
+    /**
      * Initialize the object from a parcel.
      */
     public NeighboringCellInfo(Parcel in) {
         mRssi = in.readInt();
+        mLac = in.readInt();
         mCid = in.readInt();
+        mPsc = in.readInt();
+        mNetworkType = in.readInt();
     }
 
     /**
-     * @return received signal strength in "asu", ranging from 0 - 31,
-     * or UNKNOWN_RSSI if unknown
+     * @return received signal strength or UNKNOWN_RSSI if unknown
      *
-     * For GSM, dBm = -113 + 2*asu,
+     * For GSM, it is in "asu" ranging from 0 to 31 (dBm = -113 + 2*asu)
      * 0 means "-113 dBm or less" and 31 means "-51 dBm or greater"
+     * For UMTS, it is the Level index of CPICH RSCP defined in TS 25.125
      */
     public int getRssi() {
         return mRssi;
     }
 
     /**
-     * @return cell id, UNKNOWN_CID if unknown, 0xffffffff max legal value
+     * @return LAC in GSM, 0xffff max legal value
+     *  UNKNOWN_CID if in UMTS or CMDA or unknown
+     */
+    public int getLac() {
+        return mLac;
+    }
+
+    /**
+     * @return cell id in GSM, 0xffff max legal value
+     *  UNKNOWN_CID if in UMTS or CDMA or unknown
      */
     public int getCid() {
         return mCid;
     }
 
     /**
+     * @return Primary Scrambling Code in 9 bits format in UMTS, 0x1ff max value
+     *  UNKNOWN_CID if in GSM or CMDA or unknown
+     */
+    public int getPsc() {
+        return mPsc;
+    }
+
+    /**
+     * @return Radio network type while neighboring cell location is stored.
+     *
+     * Return {@link TelephonyManager#NETWORK_TYPE_UNKNOWN TelephonyManager.NETWORK_TYPE_UNKNOWN}
+     * means that the location information is unavailable.
+     *
+     * Return {@link TelephonyManager#NETWORK_TYPE_GPRS TelephonyManager.NETWORK_TYPE_GPRS} or
+     * {@link TelephonyManager#NETWORK_TYPE_EDGE TelephonyManager.NETWORK_TYPE_EDGE}
+     * means that Neighboring Cell information is stored for GSM network, in
+     * which {@link NeighboringCellInfo#getLac NeighboringCellInfo.getLac} and
+     * {@link NeighboringCellInfo#getCid NeighboringCellInfo.getCid} should be
+     * called to access location.
+     *
+     * Return {@link TelephonyManager#NETWORK_TYPE_UMTS TelephonyManager.NETWORK_TYPE_UMTS},
+     * {@link TelephonyManager#NETWORK_TYPE_HSDPA TelephonyManager.NETWORK_TYPE_HSDPA},
+     * {@link TelephonyManager#NETWORK_TYPE_HSUPA TelephonyManager.NETWORK_TYPE_HSUPA},
+     * or {@link TelephonyManager#NETWORK_TYPE_HSPA TelephonyManager.NETWORK_TYPE_HSPA}
+     * means that Neighboring Cell information is stored for UMTS network, in
+     * which {@link NeighboringCellInfo#getPsc NeighboringCellInfo.getPsc}
+     * should be called to access location.
+     */
+    public int getNetworkType() {
+        return mNetworkType;
+    }
+    /**
+     * @deprecated
      * Set the cell id.
+     *
+     * NeighboringCellInfo is a one time shot for the neighboring cells based on
+     * the radio network type at that moment. It shouldn't be changed after
+     * creation.
      */
     public void setCid(int cid) {
         mCid = cid;
     }
 
     /**
+     * @deprecated
      * Set the signal strength of the cell.
+     *
+     * NeighboringCellInfo is a one time shot for the neighboring cells based on
+     * the radio network type at that moment. It shouldn't be changed after
+     * creation.
      */
     public void setRssi(int rssi) {
         mRssi = rssi;
@@ -95,8 +246,20 @@
 
     @Override
     public String toString() {
-        return "["+ ((mCid == UNKNOWN_CID) ? "/" : Integer.toHexString(mCid))
-        + " at " + ((mRssi == UNKNOWN_RSSI)? "/" : mRssi) + "]";
+        StringBuilder sb = new StringBuilder();
+
+        sb.append("[");
+        if (mPsc != UNKNOWN_CID) {
+            sb.append(Integer.toHexString(mPsc))
+                    .append("@").append(((mRssi == UNKNOWN_RSSI)? "-" : mRssi));
+        } else if(mLac != UNKNOWN_CID && mCid != UNKNOWN_CID) {
+            sb.append(Integer.toHexString(mLac))
+                    .append(Integer.toHexString(mCid))
+                    .append("@").append(((mRssi == UNKNOWN_RSSI)? "-" : mRssi));
+        }
+        sb.append("]");
+
+        return sb.toString();
     }
 
     public int describeContents() {
@@ -105,7 +268,10 @@
 
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(mRssi);
+        dest.writeInt(mLac);
         dest.writeInt(mCid);
+        dest.writeInt(mPsc);
+        dest.writeInt(mNetworkType);
     }
 
     public static final Parcelable.Creator<NeighboringCellInfo> CREATOR
@@ -118,6 +284,4 @@
             return new NeighboringCellInfo[size];
         }
     };
-}
-
-
+}
\ No newline at end of file
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 6664b08..fb96b2a 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -254,13 +254,13 @@
      * (@link android.Manifest.permission#ACCESS_COARSE_UPDATES}
      */
     public List<NeighboringCellInfo> getNeighboringCellInfo() {
-       try {
-           return getITelephony().getNeighboringCellInfo();
-       } catch (RemoteException ex) {
-           return null;
-       } catch (NullPointerException ex) {
-           return null;
-       }
+        try {
+            return getITelephony().getNeighboringCellInfo();
+        } catch (RemoteException ex) {
+            return null;
+        } catch (NullPointerException ex) {
+            return null;
+        }
     }
 
     /** No phone radio. */
diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java
index d1b446b..f3b59a8 100644
--- a/telephony/java/com/android/internal/telephony/RIL.java
+++ b/telephony/java/com/android/internal/telephony/RIL.java
@@ -17,6 +17,14 @@
 package com.android.internal.telephony;
 
 import static com.android.internal.telephony.RILConstants.*;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_EDGE;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_GPRS;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_UMTS;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_HSDPA;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_HSUPA;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_HSPA;
+
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -30,6 +38,7 @@
 import android.os.Message;
 import android.os.Parcel;
 import android.os.PowerManager;
+import android.os.SystemProperties;
 import android.os.PowerManager.WakeLock;
 import android.telephony.NeighboringCellInfo;
 import android.telephony.PhoneNumberUtils;
@@ -2876,21 +2885,44 @@
 
    private Object
    responseCellList(Parcel p) {
-       int num;
+       int num, rssi;
+       String location;
        ArrayList<NeighboringCellInfo> response;
        NeighboringCellInfo cell;
 
        num = p.readInt();
-       response = new ArrayList<NeighboringCellInfo>(num);
+       response = new ArrayList<NeighboringCellInfo>();
 
-       for (int i = 0 ; i < num ; i++) {
-           int rssi = p.readInt();
-           int cid = Integer.valueOf(p.readString(), 16);
-           cell = new NeighboringCellInfo(rssi, cid);
-           response.add(cell);
+       // Determine the radio access type
+       String radioString = SystemProperties.get(
+               TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE, "unknown");
+       int radioType;
+       if (radioString.equals("GPRS")) {
+           radioType = NETWORK_TYPE_GPRS;
+       } else if (radioString.equals("EDGE")) {
+           radioType = NETWORK_TYPE_EDGE;
+       } else if (radioString.equals("UMTS")) {
+           radioType = NETWORK_TYPE_UMTS;
+       } else if (radioString.equals("HSDPA")) {
+           radioType = NETWORK_TYPE_HSDPA;
+       } else if (radioString.equals("HSUPA")) {
+           radioType = NETWORK_TYPE_HSUPA;
+       } else if (radioString.equals("HSPA")) {
+           radioType = NETWORK_TYPE_HSPA;
+       } else {
+           radioType = NETWORK_TYPE_UNKNOWN;
        }
 
-    return response;
+       // Interpret the location based on radio access type
+       if (radioType != NETWORK_TYPE_UNKNOWN) {
+           for (int i = 0 ; i < num ; i++) {
+               rssi = p.readInt();
+               location = p.readString();
+               cell = new NeighboringCellInfo(rssi, location, radioType);
+               response.add(cell);
+           }
+       }
+       return response;
     }
 
     private Object responseGmsBroadcastConfig(Parcel p) {
diff --git a/tests/AndroidTests/src/com/android/unit_tests/NeighboringCellInfoTest.java b/tests/AndroidTests/src/com/android/unit_tests/NeighboringCellInfoTest.java
index 2bdf1dd..7252aa9 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/NeighboringCellInfoTest.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/NeighboringCellInfoTest.java
@@ -15,41 +15,65 @@
  */
 package com.android.unit_tests;
 
+import android.os.Parcel;
 import android.test.AndroidTestCase;
 import android.telephony.NeighboringCellInfo;
 import android.test. suitebuilder.annotation.SmallTest;
 
+import static android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_EDGE;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_GPRS;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_UMTS;
+
 public class NeighboringCellInfoTest extends AndroidTestCase {
     @SmallTest
     public void testConstructor() {
-        NeighboringCellInfo empty = new NeighboringCellInfo();
-        assertEquals(NeighboringCellInfo.UNKNOWN_RSSI, empty.getRssi());
-        assertEquals(NeighboringCellInfo.UNKNOWN_CID, empty.getCid());
-
         int rssi = 31;
-        int cid = 0xffffffff;
-        NeighboringCellInfo max = new NeighboringCellInfo(rssi, cid);
-        assertEquals(rssi, max.getRssi());
-        assertEquals(cid, max.getCid());
-    }
+        NeighboringCellInfo nc;
 
-    @SmallTest
-    public void testGetAndSet() {
-        int rssi = 16;
-        int cid = 0x12345678;
-        NeighboringCellInfo nc = new NeighboringCellInfo();
-        nc.setRssi(rssi);
-        nc.setCid(cid);
+        nc = new NeighboringCellInfo(rssi, "FFFFFFF", NETWORK_TYPE_EDGE);
+        assertEquals(NETWORK_TYPE_EDGE, nc.getNetworkType());
         assertEquals(rssi, nc.getRssi());
-        assertEquals(cid, nc.getCid());
+        assertEquals(0xfff, nc.getLac());
+        assertEquals(0xffff, nc.getCid());
+        assertEquals(NeighboringCellInfo.UNKNOWN_CID, nc.getPsc());
+
+        nc = new NeighboringCellInfo(rssi, "1FF", NETWORK_TYPE_UMTS);
+        assertEquals(NETWORK_TYPE_UMTS, nc.getNetworkType());
+        assertEquals(rssi, nc.getRssi());
+        assertEquals(NeighboringCellInfo.UNKNOWN_CID, nc.getCid());
+        assertEquals(NeighboringCellInfo.UNKNOWN_CID, nc.getLac());
+        assertEquals(0x1ff, nc.getPsc());
+
+        nc = new NeighboringCellInfo(rssi, "1FF", NETWORK_TYPE_UNKNOWN);
+        assertEquals(NETWORK_TYPE_UNKNOWN, nc.getNetworkType());
+        assertEquals(rssi, nc.getRssi());
+        assertEquals(NeighboringCellInfo.UNKNOWN_CID, nc.getCid());
+        assertEquals(NeighboringCellInfo.UNKNOWN_CID, nc.getLac());
+        assertEquals(NeighboringCellInfo.UNKNOWN_CID, nc.getPsc());
     }
 
     @SmallTest
-    public void testToString() {
-        NeighboringCellInfo empty = new NeighboringCellInfo();
-        assertEquals("[/ at /]", empty.toString());
+    public void testParcel() {
+        int rssi = 20;
 
-        NeighboringCellInfo nc = new NeighboringCellInfo(16, 0x12345678);
-        assertEquals("[12345678 at 16]", nc.toString());
-    }
+        NeighboringCellInfo nc = new NeighboringCellInfo(rssi, "12345678", NETWORK_TYPE_GPRS);
+        assertEquals(NETWORK_TYPE_GPRS, nc.getNetworkType());
+        assertEquals(rssi, nc.getRssi());
+        assertEquals(0x1234, nc.getLac());
+        assertEquals(0x5678, nc.getCid());
+        assertEquals(NeighboringCellInfo.UNKNOWN_CID, nc.getPsc());
+
+        Parcel p = Parcel.obtain();
+        p.setDataPosition(0);
+        nc.writeToParcel(p, 0);
+
+        p.setDataPosition(0);
+        NeighboringCellInfo nw = new NeighboringCellInfo(p);
+        assertEquals(NETWORK_TYPE_GPRS, nw.getNetworkType());
+        assertEquals(rssi, nw.getRssi());
+        assertEquals(0x1234, nw.getLac());
+        assertEquals(0x5678, nw.getCid());
+        assertEquals(NeighboringCellInfo.UNKNOWN_CID, nw.getPsc());
+     }
 }