am 69ef0d55: Merge "Adding missing breaks in BnSurfaceComposer::onTransact"

* commit '69ef0d55d7d7cb9b9bcccffff50ea10ac3833aaa':
  Adding missing breaks in BnSurfaceComposer::onTransact
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 4c1b997..9a9023b 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -154,7 +154,7 @@
     <string name="permgroupdesc_messages" msgid="7045736972019211994">"Lesen und schreiben Sie Ihre SMS, E-Mails und anderen Nachrichten."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Ihre persönlichen Informationen"</string>
     <string name="permgroupdesc_personalInfo" msgid="5488050357388806068">"Direkter Zugriff auf die Kontakte und den Kalender Ihres Telefons"</string>
-    <string name="permgrouplab_location" msgid="635149742436692049">"Ihren Standort"</string>
+    <string name="permgrouplab_location" msgid="635149742436692049">"Meinen Standort"</string>
     <string name="permgroupdesc_location" msgid="2430258821648348660">"Ihren physischen Standort überwachen"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Netzwerkkommunikation"</string>
     <string name="permgroupdesc_network" msgid="5035763698958415998">"Ermöglicht Anwendungen den Zugriff auf verschiedene Netzwerkfunktionen"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 90892e5..a81e73b 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -868,7 +868,7 @@
     <string name="create_contact_using" msgid="4947405226788104538">"전화번호부에"\n"<xliff:g id="NUMBER">%s</xliff:g> 추가"</string>
     <string name="accessibility_compound_button_selected" msgid="5612776946036285686">"선택함"</string>
     <string name="accessibility_compound_button_unselected" msgid="8864512895673924091">"선택 안함"</string>
-    <string name="grant_credentials_permission_message_header" msgid="6824538733852821001">"현재 이후로 하나 이상의 다음 애플리케이션이 계정에 대한 액세스 권한을 요청합니다."</string>
+    <string name="grant_credentials_permission_message_header" msgid="6824538733852821001">"다음 애플리케이션에서 계정 액세스 요청이 들어왔습니다."</string>
     <string name="grant_credentials_permission_message_footer" msgid="3125211343379376561">"요청을 허용하시겠습니까?"</string>
     <string name="grant_permissions_header_text" msgid="2722567482180797717">"액세스 요청"</string>
     <string name="allow" msgid="7225948811296386551">"허용"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 35f290b..a5827c4 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -68,7 +68,7 @@
     <string name="serviceNotProvisioned" msgid="8614830180508686666">"無法提供此服務。"</string>
     <string name="CLIRPermanent" msgid="5460892159398802465">"本機號碼顯示設定無法變更。"</string>
     <string name="RestrictedChangedTitle" msgid="5592189398956187498">"受限存取已變更"</string>
-    <string name="RestrictedOnData" msgid="8653794784690065540">"已封鎖資料傳輸服務。"</string>
+    <string name="RestrictedOnData" msgid="8653794784690065540">"已封鎖數據傳輸服務。"</string>
     <string name="RestrictedOnEmergency" msgid="6581163779072833665">"已封鎖緊急服務。"</string>
     <string name="RestrictedOnNormal" msgid="4953867011389750673">"已封鎖語音服務。"</string>
     <string name="RestrictedOnAllVoice" msgid="1459318899842232234">"已封鎖所有語音服務。"</string>
@@ -622,15 +622,15 @@
     <string name="beforeOneMonthDurationPast" msgid="909134546836499826">"1 個月前"</string>
   <plurals name="num_seconds_ago">
     <item quantity="one" msgid="4869870056547896011">"1 秒以前"</item>
-    <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> 秒以前"</item>
+    <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> 秒前"</item>
   </plurals>
   <plurals name="num_minutes_ago">
     <item quantity="one" msgid="3306787433088810191">"1 分鐘以前"</item>
-    <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> 分鐘以前"</item>
+    <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> 分鐘前"</item>
   </plurals>
   <plurals name="num_hours_ago">
     <item quantity="one" msgid="9150797944610821849">"1 小時以前"</item>
-    <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> 小時以前"</item>
+    <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> 小時前"</item>
   </plurals>
   <plurals name="last_num_days">
     <item quantity="other" msgid="3069992808164318268">"最近 <xliff:g id="COUNT">%d</xliff:g> 天"</item>
@@ -639,7 +639,7 @@
     <string name="older" msgid="5211975022815554840">"較舊"</string>
   <plurals name="num_days_ago">
     <item quantity="one" msgid="861358534398115820">"昨天"</item>
-    <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> 天以前"</item>
+    <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> 天前"</item>
   </plurals>
   <plurals name="in_num_seconds">
     <item quantity="one" msgid="2729745560954905102">"1 秒內"</item>
@@ -667,11 +667,11 @@
   </plurals>
   <plurals name="abbrev_num_hours_ago">
     <item quantity="one" msgid="4796212039724722116">"1 小時以前"</item>
-    <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> 小時以前"</item>
+    <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> 小時前"</item>
   </plurals>
   <plurals name="abbrev_num_days_ago">
     <item quantity="one" msgid="8463161711492680309">"昨天"</item>
-    <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> 天以前"</item>
+    <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> 天前"</item>
   </plurals>
   <plurals name="abbrev_in_num_seconds">
     <item quantity="one" msgid="5842225370795066299">"1 秒內"</item>
@@ -838,14 +838,14 @@
     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"USB 儲存裝置已毀損"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"SD 卡已損壞"</string>
     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"USB 儲存裝置已損壞,您可能必須重新格式化。"</string>
-    <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"SD 卡已毀損,您可能必須予以重新格式化。"</string>
-    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"USB 儲存裝置已意外移除"</string>
+    <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"SD 卡已毀損,您可能必須重新格式化。"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"USB 儲存裝置未正常移除"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"SD 卡未正常移除"</string>
     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"請先卸載 USB 儲存裝置,再將其移除,以免資料遺失。"</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"請先卸載 SD 卡,再將其移除,以免資料遺失。"</string>
     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"USB 儲存裝置已可安全移除"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"可安全移除 SD 卡"</string>
-    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"您可安全移除 USB 儲存裝置了。"</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"您現在可以安全地移除 USB 儲存裝置。"</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"您現在可以安全地移除 SD 卡。"</string>
     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"USB 儲存裝置已移除"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"已移除 SD 卡"</string>
diff --git a/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java b/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
index 9bd8f36..6001be9 100644
--- a/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
+++ b/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
@@ -56,13 +56,21 @@
     public static final String ACTION_RF_FIELD_OFF_DETECTED =
             "com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED";
 
-    // protected by NfcAdapterExtras.class, and final after first construction
+    // protected by NfcAdapterExtras.class, and final after first construction,
+    // except for attemptDeadServiceRecovery() when NFC crashes - we accept a
+    // best effort recovery
+    private static NfcAdapter sAdapter;
     private static INfcAdapterExtras sService;
     private static NfcAdapterExtras sSingleton;
     private static NfcExecutionEnvironment sEmbeddedEe;
     private static CardEmulationRoute sRouteOff;
     private static CardEmulationRoute sRouteOnWhenScreenOn;
 
+    /** get service handles */
+    private static void initService() {
+        sService = sAdapter.getNfcAdapterExtrasInterface();
+    }
+
     /**
      * Get the {@link NfcAdapterExtras} for the given {@link NfcAdapter}.
      *
@@ -76,12 +84,13 @@
         synchronized(NfcAdapterExtras.class) {
             if (sSingleton == null) {
                 try {
-                    sService = adapter.getNfcAdapterExtrasInterface();
-                    sEmbeddedEe = new NfcExecutionEnvironment(sService);
+                    sAdapter = adapter;
                     sRouteOff = new CardEmulationRoute(CardEmulationRoute.ROUTE_OFF, null);
+                    sSingleton = new NfcAdapterExtras();
+                    sEmbeddedEe = new NfcExecutionEnvironment(sSingleton);
                     sRouteOnWhenScreenOn = new CardEmulationRoute(
                             CardEmulationRoute.ROUTE_ON_WHEN_SCREEN_ON, sEmbeddedEe);
-                    sSingleton = new NfcAdapterExtras();
+                    initService();
                 } finally {
                     if (sSingleton == null) {
                         sService = null;
@@ -136,6 +145,19 @@
     }
 
     /**
+     * NFC service dead - attempt best effort recovery
+     */
+    void attemptDeadServiceRecovery(Exception e) {
+        Log.e(TAG, "NFC Adapter Extras dead - attempting to recover");
+        sAdapter.attemptDeadServiceRecovery(e);
+        initService();
+    }
+
+    INfcAdapterExtras getService() {
+        return sService;
+    }
+
+    /**
      * Get the routing state of this NFC EE.
      *
      * <p class="note">
@@ -150,7 +172,7 @@
                     sRouteOff :
                     sRouteOnWhenScreenOn;
         } catch (RemoteException e) {
-            Log.e(TAG, "", e);
+            attemptDeadServiceRecovery(e);
             return sRouteOff;
         }
     }
@@ -169,7 +191,7 @@
         try {
             sService.setCardEmulationRoute(route.route);
         } catch (RemoteException e) {
-            Log.e(TAG, "", e);
+            attemptDeadServiceRecovery(e);
         }
     }
 
@@ -190,7 +212,7 @@
         try {
             sService.registerTearDownApdus(packageName, apdus);
         } catch (RemoteException e) {
-            Log.e(TAG, "", e);
+            attemptDeadServiceRecovery(e);
         }
     }
 
@@ -198,7 +220,7 @@
         try {
             sService.unregisterTearDownApdus(packageName);
         } catch (RemoteException e) {
-            Log.e(TAG, "", e);
+            attemptDeadServiceRecovery(e);
         }
     }
 }
diff --git a/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java b/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java
index 3efe492..eb2f6f8 100644
--- a/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java
+++ b/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java
@@ -29,7 +29,7 @@
 import android.os.RemoteException;
 
 public class NfcExecutionEnvironment {
-    private final INfcAdapterExtras mService;
+    private final NfcAdapterExtras mExtras;
 
     /**
      * Broadcast Action: An ISO-DEP AID was selected.
@@ -55,8 +55,8 @@
      */
     public static final String EXTRA_AID = "com.android.nfc_extras.extra.AID";
 
-    NfcExecutionEnvironment(INfcAdapterExtras service) {
-        mService = service;
+    NfcExecutionEnvironment(NfcAdapterExtras extras) {
+        mExtras = extras;
     }
 
     /**
@@ -75,10 +75,11 @@
      */
     public void open() throws IOException {
         try {
-            Bundle b = mService.open(new Binder());
+            Bundle b = mExtras.getService().open(new Binder());
             throwBundle(b);
         } catch (RemoteException e) {
-            return;
+            mExtras.attemptDeadServiceRecovery(e);
+            throw new IOException("NFC Service was dead, try again");
         }
     }
 
@@ -92,9 +93,10 @@
      */
     public void close() throws IOException {
         try {
-            throwBundle(mService.close());
+            throwBundle(mExtras.getService().close());
         } catch (RemoteException e) {
-            return;
+            mExtras.attemptDeadServiceRecovery(e);
+            throw new IOException("NFC Service was dead");
         }
     }
 
@@ -109,9 +111,10 @@
     public byte[] transceive(byte[] in) throws IOException {
         Bundle b;
         try {
-            b = mService.transceive(in);
+            b = mExtras.getService().transceive(in);
         } catch (RemoteException e) {
-            throw new IOException(e.getMessage());
+            mExtras.attemptDeadServiceRecovery(e);
+            throw new IOException("NFC Service was dead, need to re-open");
         }
         throwBundle(b);
         return b.getByteArray("out");
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index bf2d033..90295e0 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -23,6 +23,18 @@
 import static android.net.wifi.WifiManager.WIFI_STATE_UNKNOWN;
 
 import android.app.ActivityManagerNative;
+import android.app.AlarmManager;
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHeadset;
+import android.bluetooth.BluetoothA2dp;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.database.ContentObserver;
 import android.net.NetworkInfo;
 import android.net.NetworkStateTracker;
 import android.net.DhcpInfo;
@@ -32,8 +44,10 @@
 import android.net.NetworkInfo.State;
 import android.os.Message;
 import android.os.Parcelable;
+import android.os.PowerManager;
 import android.os.Handler;
 import android.os.HandlerThread;
+import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.Looper;
 import android.os.RemoteException;
@@ -44,15 +58,6 @@
 import android.util.EventLog;
 import android.util.Log;
 import android.util.Config;
-import android.app.Notification;
-import android.app.PendingIntent;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothHeadset;
-import android.bluetooth.BluetoothA2dp;
-import android.content.ContentResolver;
-import android.content.Intent;
-import android.content.Context;
-import android.database.ContentObserver;
 import com.android.internal.app.IBatteryStats;
 
 import java.net.UnknownHostException;
@@ -91,15 +96,16 @@
     private static final int EVENT_INTERFACE_CONFIGURATION_FAILED    = 7;
     private static final int EVENT_POLL_INTERVAL                     = 8;
     private static final int EVENT_DHCP_START                        = 9;
-    private static final int EVENT_DEFERRED_DISCONNECT               = 10;
-    private static final int EVENT_DEFERRED_RECONNECT                = 11;
+    private static final int EVENT_DHCP_RENEW                        = 10;
+    private static final int EVENT_DEFERRED_DISCONNECT               = 11;
+    private static final int EVENT_DEFERRED_RECONNECT                = 12;
     /**
      * The driver is started or stopped. The object will be the state: true for
      * started, false for stopped.
      */
-    private static final int EVENT_DRIVER_STATE_CHANGED              = 12;
-    private static final int EVENT_PASSWORD_KEY_MAY_BE_INCORRECT     = 13;
-    private static final int EVENT_MAYBE_START_SCAN_POST_DISCONNECT  = 14;
+    private static final int EVENT_DRIVER_STATE_CHANGED              = 13;
+    private static final int EVENT_PASSWORD_KEY_MAY_BE_INCORRECT     = 14;
+    private static final int EVENT_MAYBE_START_SCAN_POST_DISCONNECT  = 15;
 
     /**
      * The driver state indication.
@@ -218,6 +224,15 @@
     private boolean mUseStaticIp = false;
     private int mReconnectCount;
 
+    private AlarmManager mAlarmManager;
+    private PendingIntent mDhcpRenewalIntent;
+    private PowerManager.WakeLock mDhcpRenewWakeLock;
+    private static final String WAKELOCK_TAG = "*wifi*";
+
+    private static final int DHCP_RENEW = 0;
+    private static final String ACTION_DHCP_RENEW = "android.net.wifi.DHCP_RENEW";
+
+
     /* Tracks if any network in the configuration is disabled */
     private AtomicBoolean mIsAnyNetworkDisabled = new AtomicBoolean(false);
 
@@ -386,6 +401,27 @@
         mDhcpInfo = new DhcpInfo();
         mRunState = RUN_STATE_STARTING;
 
+        mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
+        Intent dhcpRenewalIntent = new Intent(ACTION_DHCP_RENEW, null);
+        mDhcpRenewalIntent = PendingIntent.getBroadcast(mContext, DHCP_RENEW, dhcpRenewalIntent, 0);
+
+        mContext.registerReceiver(
+            new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    //DHCP renew
+                    if (mDhcpTarget != null) {
+                        Log.d(TAG, "Sending a DHCP renewal");
+                        //acquire a 40s wakelock to finish DHCP renewal
+                        mDhcpRenewWakeLock.acquire(40000);
+                        mDhcpTarget.sendEmptyMessage(EVENT_DHCP_RENEW);
+                    }
+                }
+            },new IntentFilter(ACTION_DHCP_RENEW));
+
+        PowerManager powerManager = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
+        mDhcpRenewWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG);
+
         // Setting is in seconds
         NOTIFICATION_REPEAT_DELAY_MS = Settings.Secure.getInt(context.getContentResolver(), 
                 Settings.Secure.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, 900) * 1000l;
@@ -2389,7 +2425,7 @@
 
     private class DhcpHandler extends Handler {
 
-        private Handler mTarget;
+        private Handler mWifiStateTrackerHandler;
         
         /**
          * Whether to skip the DHCP result callback to the target. For example,
@@ -2410,10 +2446,10 @@
          * in an error state and we will not disable coexistence.
          */
         private BluetoothHeadset mBluetoothHeadset;
-        
+
         public DhcpHandler(Looper looper, Handler target) {
             super(looper);
-            mTarget = target;
+            mWifiStateTrackerHandler = target;
             
             mBluetoothHeadset = new BluetoothHeadset(mContext, null);
         }
@@ -2423,7 +2459,7 @@
 
             switch (msg.what) {
                 case EVENT_DHCP_START:
-                    
+                case EVENT_DHCP_RENEW:
                     boolean modifiedBluetoothCoexistenceMode = false;
                     int powerMode = DRIVER_POWER_MODE_AUTO;
 
@@ -2465,14 +2501,70 @@
                         // A new request is being made, so assume we will callback
                         mCancelCallback = false;
                     }
-                    Log.d(TAG, "DhcpHandler: DHCP request started");
-                    if (NetworkUtils.runDhcp(mInterfaceName, mDhcpInfo)) {
-                        event = EVENT_INTERFACE_CONFIGURATION_SUCCEEDED;
-                        if (LOCAL_LOGD) Log.v(TAG, "DhcpHandler: DHCP request succeeded");
-                    } else {
-                        event = EVENT_INTERFACE_CONFIGURATION_FAILED;
-                        Log.i(TAG, "DhcpHandler: DHCP request failed: " +
-                            NetworkUtils.getDhcpError());
+
+                    if (msg.what == EVENT_DHCP_START) {
+                        Log.d(TAG, "DHCP request started");
+                        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 {
+                            event = EVENT_INTERFACE_CONFIGURATION_FAILED;
+                            Log.e(TAG, "DHCP request failed: " + NetworkUtils.getDhcpError());
+                        }
+                        synchronized (this) {
+                            if (!mCancelCallback) {
+                                mWifiStateTrackerHandler.sendEmptyMessage(event);
+                            }
+                        }
+
+                    } else if (msg.what == EVENT_DHCP_RENEW) {
+                        Log.d(TAG, "DHCP renewal started");
+                        int oIp = mDhcpInfo.ipAddress;
+                        int oGw = mDhcpInfo.gateway;
+                        int oMsk = mDhcpInfo.netmask;
+                        int oDns1 = mDhcpInfo.dns1;
+                        int oDns2 = mDhcpInfo.dns2;
+
+                        if (NetworkUtils.runDhcpRenew(mInterfaceName, mDhcpInfo)) {
+                            Log.d(TAG, "DHCP renewal with lease: " + mDhcpInfo.leaseDuration);
+
+                            boolean changed =
+                                (oIp   != mDhcpInfo.ipAddress ||
+                                 oGw   != mDhcpInfo.gateway ||
+                                 oMsk  != mDhcpInfo.netmask ||
+                                 oDns1 != mDhcpInfo.dns1 ||
+                                 oDns2 != mDhcpInfo.dns2);
+
+                            if (changed) {
+                                Log.d(TAG, "IP config change on renewal");
+                                mWifiInfo.setIpAddress(mDhcpInfo.ipAddress);
+                                NetworkUtils.resetConnections(mInterfaceName);
+                                msg = mTarget.obtainMessage(EVENT_CONFIGURATION_CHANGED,
+                                        mNetworkInfo);
+                                msg.sendToTarget();
+                            }
+
+                            mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+                                    SystemClock.elapsedRealtime() +
+                                    mDhcpInfo.leaseDuration * 480,
+                                    mDhcpRenewalIntent);
+                        } else {
+                            event = EVENT_INTERFACE_CONFIGURATION_FAILED;
+                            Log.d(TAG, "DHCP renewal failed: " + NetworkUtils.getDhcpError());
+
+                            synchronized (this) {
+                                if (!mCancelCallback) {
+                                    mWifiStateTrackerHandler.sendEmptyMessage(event);
+                                }
+                            }
+                        }
                     }
 
                     if (powerMode != DRIVER_POWER_MODE_ACTIVE) {
@@ -2485,17 +2577,15 @@
                                 WifiNative.BLUETOOTH_COEXISTENCE_MODE_SENSE);
                     }
 
-                    synchronized (this) {
-                        if (!mCancelCallback) {
-                            mTarget.sendEmptyMessage(event);
-                        }
-                    }
                     break;
             }
         }
 
         public synchronized void setCancelCallback(boolean cancelCallback) {
             mCancelCallback = cancelCallback;
+            if (cancelCallback) {
+                mAlarmManager.cancel(mDhcpRenewalIntent);
+            }
         }
 
         /**
@@ -2511,6 +2601,7 @@
             int state = mBluetoothHeadset.getState(mBluetoothHeadset.getCurrentHeadset());
             return state == BluetoothHeadset.STATE_DISCONNECTED;
         }
+
     }
     
     private void checkUseStaticIp() {