merge in gingerbread-release history after reset to gingerbread
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index fdc3679..91cc3ed 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -183,6 +183,8 @@
     <string name="permdesc_receiveSms" msgid="6298292335965966117">"Aplikaciji omogućuje primanje i obradu SMS poruka. Zlonamjerne aplikacije mogu pratiti vaše poruke ili ih izbrisati prije nego što ih vi vidite."</string>
     <string name="permlab_receiveMms" msgid="8894700916188083287">"primanje MMS-a"</string>
     <string name="permdesc_receiveMms" msgid="4563346832000174373">"Aplikaciji omogućuje primanje i obradu MMS poruka. Zlonamjerne aplikacije mogu pratiti vaše poruke ili ih izbrisati prije nego što ih vi vidite."</string>
+    <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"primanje hitnih odašiljanja"</string>
+    <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Omogućuje aplikaciji primanje i obradu poruka hitnih odašiljanja. Ta je dozvola dostupna samo aplikacijama sustava."</string>
     <string name="permlab_sendSms" msgid="5600830612147671529">"slanje SMS poruka"</string>
     <string name="permdesc_sendSms" msgid="1946540351763502120">"Aplikaciji omogućuje slanje SMS poruka. Zlonamjerne aplikacije mogu stvarati troškove slanjem poruka bez vaše potvrde."</string>
     <string name="permlab_readSms" msgid="4085333708122372256">"čitanje SMS-a ili MMS-a"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 032ec29..779028e 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -461,4 +461,11 @@
     <!-- Set to true if the RSSI should always display CDMA signal strength
          even on EVDO -->
     <bool name="config_alwaysUseCdmaRssi">false</bool>
+
+    <!-- If this value is true, duplicate Source/Destination port fields
+         in WDP header of some carriers OMADM wap push are supported.
+         ex: MSGTYPE-TotalSegments-CurrentSegment
+             -SourcePortDestPort-SourcePortDestPort-OMADM PDU
+         If false, not supported. -->
+    <bool name="config_duplicate_port_omadm_wappush">false</bool>
 </resources>
diff --git a/include/utils/RefBase.h b/include/utils/RefBase.h
index 1b4a310..d92cfb0 100644
--- a/include/utils/RefBase.h
+++ b/include/utils/RefBase.h
@@ -112,17 +112,23 @@
         getWeakRefs()->trackMe(enable, retain); 
     }
 
+    // used to override the RefBase destruction.
+    class Destroyer {
+        friend class RefBase;
+    public:
+        virtual ~Destroyer();
+    private:
+        virtual void destroy(RefBase const* base) = 0;
+    };
+
+    // Make sure to never acquire a strong reference from this function. The
+    // same restrictions than for destructors apply.
+    void setDestroyer(Destroyer* destroyer);
+
 protected:
                             RefBase();
     virtual                 ~RefBase();
 
-    // called when the last reference goes away. this is responsible for
-    // calling the destructor. The default implementation just does
-    // "delete this;".
-    // Make sure to never acquire a strong reference from this function. The
-    // same restrictions than for destructors apply.
-    virtual void            destroy() const;
-
     //! Flags for extendObjectLifetime()
     enum {
         OBJECT_LIFETIME_WEAK    = 0x0001,
diff --git a/libs/utils/RefBase.cpp b/libs/utils/RefBase.cpp
index 1c870cf..47ef546 100644
--- a/libs/utils/RefBase.cpp
+++ b/libs/utils/RefBase.cpp
@@ -48,6 +48,11 @@
 
 // ---------------------------------------------------------------------------
 
+RefBase::Destroyer::~Destroyer() {
+}
+
+// ---------------------------------------------------------------------------
+
 class RefBase::weakref_impl : public RefBase::weakref_type
 {
 public:
@@ -55,7 +60,7 @@
     volatile int32_t    mWeak;
     RefBase* const      mBase;
     volatile int32_t    mFlags;
-
+    Destroyer*          mDestroyer;
 
 #if !DEBUG_REFS
 
@@ -64,6 +69,7 @@
         , mWeak(0)
         , mBase(base)
         , mFlags(0)
+        , mDestroyer(0)
     {
     }
 
@@ -298,10 +304,6 @@
     const_cast<RefBase*>(this)->onFirstRef();
 }
 
-void RefBase::destroy() const {
-    delete this;
-}
-
 void RefBase::decStrong(const void* id) const
 {
     weakref_impl* const refs = mRefs;
@@ -314,7 +316,11 @@
     if (c == 1) {
         const_cast<RefBase*>(this)->onLastStrongRef(id);
         if ((refs->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {
-            destroy();
+            if (refs->mDestroyer) {
+                refs->mDestroyer->destroy(this);
+            } else {
+                delete this;
+            }
         }
     }
     refs->removeWeakRef(id);
@@ -349,7 +355,9 @@
     return mRefs->mStrong;
 }
 
-
+void RefBase::setDestroyer(RefBase::Destroyer* destroyer) {
+    mRefs->mDestroyer = destroyer;
+}
 
 RefBase* RefBase::weakref_type::refBase() const
 {
@@ -375,7 +383,11 @@
     if ((impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {
         if (impl->mStrong == INITIAL_STRONG_VALUE) {
             if (impl->mBase) {
-                impl->mBase->destroy();
+                if (impl->mDestroyer) {
+                    impl->mDestroyer->destroy(impl->mBase);
+                } else {
+                    delete impl->mBase;
+                }
             }
         } else {
             // LOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
@@ -385,7 +397,11 @@
         impl->mBase->onLastWeakRef(id);
         if ((impl->mFlags&OBJECT_LIFETIME_FOREVER) != OBJECT_LIFETIME_FOREVER) {
             if (impl->mBase) {
-                impl->mBase->destroy();
+                if (impl->mDestroyer) {
+                    impl->mDestroyer->destroy(impl->mBase);
+                } else {
+                    delete impl->mBase;
+                }
             }
         }
     }
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 4739cc3..0087fd5 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -60,6 +60,7 @@
         mWidth(0), mHeight(0), mNeedsScaling(false), mFixedSize(false),
         mBypassState(false)
 {
+    setDestroyer(this);
 }
 
 Layer::~Layer()
@@ -76,8 +77,8 @@
     }
 }
 
-void Layer::destroy() const {
-    mFlinger->destroyLayer(this);
+void Layer::destroy(RefBase const* base) {
+    mFlinger->destroyLayer(static_cast<LayerBase const*>(base));
 }
 
 status_t Layer::setToken(const sp<UserClient>& userClient,
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 51b52f9..2c4f756 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -44,7 +44,7 @@
 
 // ---------------------------------------------------------------------------
 
-class Layer : public LayerBaseClient
+class Layer : public LayerBaseClient, private RefBase::Destroyer
 {
 public:
             Layer(SurfaceFlinger* flinger, DisplayID display,
@@ -94,7 +94,7 @@
         return mFreezeLock; }
 
 protected:
-    virtual void destroy() const;
+    virtual void destroy(RefBase const* base);
     virtual void dump(String8& result, char* scratch, size_t size) const;
 
 private:
diff --git a/telephony/java/com/android/internal/telephony/WapPushOverSms.java b/telephony/java/com/android/internal/telephony/WapPushOverSms.java
old mode 100644
new mode 100755
index 168b63b..d661640
--- a/telephony/java/com/android/internal/telephony/WapPushOverSms.java
+++ b/telephony/java/com/android/internal/telephony/WapPushOverSms.java
@@ -135,6 +135,9 @@
                 case WspTypeDecoder.CONTENT_TYPE_B_SUPL_INIT:
                     mimeType = WspTypeDecoder.CONTENT_MIME_TYPE_B_SUPL_INIT;
                     break;
+                case WspTypeDecoder.CONTENT_TYPE_B_PUSH_SYNCML_NOTI:
+                    mimeType = WspTypeDecoder.CONTENT_MIME_TYPE_B_PUSH_SYNCML_NOTI;
+                    break;
                 default:
                     if (Config.LOGD) {
                         Log.w(LOG_TAG,
@@ -159,6 +162,8 @@
                 binaryContentType = WspTypeDecoder.CONTENT_TYPE_B_VND_DOCOMO_PF;
             } else if (mimeType.equals(WspTypeDecoder.CONTENT_MIME_TYPE_B_SUPL_INIT)) {
                 binaryContentType = WspTypeDecoder.CONTENT_TYPE_B_SUPL_INIT;
+            } else if (mimeType.equals(WspTypeDecoder.CONTENT_MIME_TYPE_B_PUSH_SYNCML_NOTI)) {
+                binaryContentType = WspTypeDecoder.CONTENT_TYPE_B_PUSH_SYNCML_NOTI;
             } else {
                 if (Config.LOGD) Log.w(LOG_TAG, "Received PDU. Unknown Content-Type = " + mimeType);
                 return Intents.RESULT_SMS_HANDLED;
diff --git a/telephony/java/com/android/internal/telephony/WspTypeDecoder.java b/telephony/java/com/android/internal/telephony/WspTypeDecoder.java
old mode 100644
new mode 100755
index 5dc89f0..01206fd
--- a/telephony/java/com/android/internal/telephony/WspTypeDecoder.java
+++ b/telephony/java/com/android/internal/telephony/WspTypeDecoder.java
@@ -41,6 +41,7 @@
     public static final int CONTENT_TYPE_B_MMS = 0x3e;
     public static final int CONTENT_TYPE_B_VND_DOCOMO_PF = 0x0310;
     public static final int CONTENT_TYPE_B_SUPL_INIT = 0x312;
+    public static final int CONTENT_TYPE_B_PUSH_SYNCML_NOTI = 0x44;
 
     public static final String CONTENT_MIME_TYPE_B_DRM_RIGHTS_XML =
             "application/vnd.oma.drm.rights+xml";
@@ -52,10 +53,11 @@
     public static final String CONTENT_MIME_TYPE_B_MMS = "application/vnd.wap.mms-message";
     public static final String CONTENT_MIME_TYPE_B_VND_DOCOMO_PF = "application/vnd.docomo.pf";
     public static final String CONTENT_MIME_TYPE_B_SUPL_INIT = "application/vnd.omaloc-supl-init";
+    public static final String CONTENT_MIME_TYPE_B_PUSH_SYNCML_NOTI =
+            "application/vnd.syncml.notification";
 
     public static final int PARAMETER_ID_X_WAP_APPLICATION_ID = 0x2f;
 
-
     byte[] wspData;
     int    dataLength;
     long   unsigned32bit;
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
old mode 100644
new mode 100755
index 45b58e5..e409646
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
@@ -42,6 +42,7 @@
 import com.android.internal.telephony.SmsMessageBase;
 import com.android.internal.telephony.SmsMessageBase.TextEncodingDetails;
 import com.android.internal.telephony.TelephonyProperties;
+import com.android.internal.telephony.WspTypeDecoder;
 import com.android.internal.telephony.cdma.sms.SmsEnvelope;
 import com.android.internal.telephony.cdma.sms.UserData;
 import com.android.internal.util.HexDump;
@@ -51,6 +52,8 @@
 import java.util.Arrays;
 import java.util.HashMap;
 
+import android.content.res.Resources;
+
 
 final class CdmaSMSDispatcher extends SMSDispatcher {
     private static final String TAG = "CDMA";
@@ -58,6 +61,9 @@
     private byte[] mLastDispatchedSmsFingerprint;
     private byte[] mLastAcknowledgedSmsFingerprint;
 
+    private boolean mCheckForDuplicatePortsInOmadmWapPush = Resources.getSystem().getBoolean(
+            com.android.internal.R.bool.config_duplicate_port_omadm_wappush);
+
     CdmaSMSDispatcher(CDMAPhone phone) {
         super(phone);
     }
@@ -245,6 +251,13 @@
             sourcePort |= 0xFF & pdu[index++];
             destinationPort = (0xFF & pdu[index++]) << 8;
             destinationPort |= 0xFF & pdu[index++];
+            // Some carriers incorrectly send duplicate port fields in omadm wap pushes.
+            // If configured, check for that here
+            if (mCheckForDuplicatePortsInOmadmWapPush) {
+                if (checkDuplicatePortOmadmWappush(pdu,index)) {
+                    index = index + 4; // skip duplicate port fields
+                }
+            }
         }
 
         // Lookup all other related parts
@@ -488,4 +501,45 @@
             return CommandsInterface.CDMA_SMS_FAIL_CAUSE_ENCODING_PROBLEM;
         }
     }
+
+    /**
+     * Optional check to see if the received WapPush is an OMADM notification with erroneous
+     * extra port fields.
+     * - Some carriers make this mistake.
+     * ex: MSGTYPE-TotalSegments-CurrentSegment
+     *       -SourcePortDestPort-SourcePortDestPort-OMADM PDU
+     * @param origPdu The WAP-WDP PDU segment
+     * @param index Current Index while parsing the PDU.
+     * @return True if OrigPdu is OmaDM Push Message which has duplicate ports.
+     *         False if OrigPdu is NOT OmaDM Push Message which has duplicate ports.
+     */
+    private boolean checkDuplicatePortOmadmWappush(byte[] origPdu, int index) {
+        index += 4;
+        byte[] omaPdu = new byte[origPdu.length - index];
+        System.arraycopy(origPdu, index, omaPdu, 0, omaPdu.length);
+
+        WspTypeDecoder pduDecoder = new WspTypeDecoder(omaPdu);
+        int wspIndex = 2;
+
+        // Process header length field
+        if (pduDecoder.decodeUintvarInteger(wspIndex) == false) {
+            return false;
+        }
+
+        wspIndex += pduDecoder.getDecodedDataLength(); // advance to next field
+
+        // Process content type field
+        if (pduDecoder.decodeContentType(wspIndex) == false) {
+            return false;
+        }
+
+        String mimeType = pduDecoder.getValueString();
+        if (mimeType == null) {
+            int binaryContentType = (int)pduDecoder.getValue32();
+            if (binaryContentType == WspTypeDecoder.CONTENT_TYPE_B_PUSH_SYNCML_NOTI) {
+                return true;
+            }
+        }
+        return false;
+    }
 }
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index f313259..e645019 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -166,6 +166,9 @@
      */
     private static final int DEFAULT_MAX_DHCP_RETRIES = 9;
 
+    //Minimum dhcp lease duration for renewal
+    private static final int MIN_RENEWAL_TIME_SECS = 5 * 60; //5 minutes
+
     private static final int DRIVER_POWER_MODE_AUTO = 0;
     private static final int DRIVER_POWER_MODE_ACTIVE = 1;
 
@@ -2506,14 +2509,8 @@
                         if (NetworkUtils.runDhcp(mInterfaceName, mDhcpInfo)) {
                             event = EVENT_INTERFACE_CONFIGURATION_SUCCEEDED;
                             Log.d(TAG, "DHCP succeeded with lease: " + mDhcpInfo.leaseDuration);
-                            //Do it a bit earlier than half the lease duration time
-                            //to beat the native DHCP client and avoid extra packets
-                            //48% for one hour lease time = 29 minutes
-                            mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
-                                    SystemClock.elapsedRealtime() +
-                                    mDhcpInfo.leaseDuration * 480, //in milliseconds
-                                    mDhcpRenewalIntent);
-                        } else {
+                            setDhcpRenewalAlarm(mDhcpInfo.leaseDuration);
+                       } else {
                             event = EVENT_INTERFACE_CONFIGURATION_FAILED;
                             Log.e(TAG, "DHCP request failed: " + NetworkUtils.getDhcpError());
                         }
@@ -2550,10 +2547,7 @@
                                 msg.sendToTarget();
                             }
 
-                            mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
-                                    SystemClock.elapsedRealtime() +
-                                    mDhcpInfo.leaseDuration * 480,
-                                    mDhcpRenewalIntent);
+                            setDhcpRenewalAlarm(mDhcpInfo.leaseDuration);
                         } else {
                             event = EVENT_INTERFACE_CONFIGURATION_FAILED;
                             Log.d(TAG, "DHCP renewal failed: " + NetworkUtils.getDhcpError());
@@ -2601,6 +2595,19 @@
             return state == BluetoothHeadset.STATE_DISCONNECTED;
         }
 
+        private void setDhcpRenewalAlarm(long leaseDuration) {
+            //Do it a bit earlier than half the lease duration time
+            //to beat the native DHCP client and avoid extra packets
+            //48% for one hour lease time = 29 minutes
+            if (leaseDuration < MIN_RENEWAL_TIME_SECS) {
+                leaseDuration = MIN_RENEWAL_TIME_SECS;
+            }
+            mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+                    SystemClock.elapsedRealtime() +
+                    leaseDuration * 480, //in milliseconds
+                    mDhcpRenewalIntent);
+        }
+
     }
     
     private void checkUseStaticIp() {