Issue an error when VPN connection is lost.

+ Add new error code CONNECTION_LOST to VpnManager.
+ Make VpnService call onError() instead of onDisconnect() when
connection is lost.
+ Make VpnService broadcast CONNECTION_LOST when that happens.
diff --git a/packages/VpnServices/src/com/android/server/vpn/VpnService.java b/packages/VpnServices/src/com/android/server/vpn/VpnService.java
index b85005c..f410c7b 100644
--- a/packages/VpnServices/src/com/android/server/vpn/VpnService.java
+++ b/packages/VpnServices/src/com/android/server/vpn/VpnService.java
@@ -147,8 +147,7 @@
 
     synchronized boolean onConnect(String username, String password) {
         try {
-            mState = VpnState.CONNECTING;
-            broadcastConnectivity(VpnState.CONNECTING);
+            setState(VpnState.CONNECTING);
 
             stopPreviouslyRunDaemons();
             String serverIp = getIp(getProfile().getServerName());
@@ -166,8 +165,7 @@
     synchronized void onDisconnect() {
         try {
             Log.i(TAG, "disconnecting VPN...");
-            mState = VpnState.DISCONNECTING;
-            broadcastConnectivity(VpnState.DISCONNECTING);
+            setState(VpnState.DISCONNECTING);
             mNotification.showDisconnect();
 
             mDaemonHelper.stopAll();
@@ -235,14 +233,13 @@
         saveOriginalDns();
         saveAndSetDomainSuffices();
 
-        mState = VpnState.CONNECTED;
         mStartTime = System.currentTimeMillis();
 
         // set DNS after saving the states in case the process gets killed
         // before states are saved
         saveSelf();
         setVpnDns();
-        broadcastConnectivity(VpnState.CONNECTED);
+        setState(VpnState.CONNECTED);
 
         enterConnectivityLoop();
     }
@@ -256,16 +253,23 @@
 
         if (mState == VpnState.IDLE) return;
 
+        // keep the notification when error occurs
+        if (!anyError()) mNotification.disableNotification();
+
         restoreOriginalDns();
         restoreOriginalDomainSuffices();
-        mState = VpnState.IDLE;
-        broadcastConnectivity(VpnState.IDLE);
+        setState(VpnState.IDLE);
 
         // stop the service itself
+        SystemProperties.set(VPN_STATUS, VPN_IS_DOWN);
         mContext.removeStates();
         mContext.stopSelf();
     }
 
+    private boolean anyError() {
+        return (mError != null);
+    }
+
     private void restoreOriginalDns() {
         // restore only if they are not overridden
         String vpnDns1 = SystemProperties.get(VPN_DNS1);
@@ -309,6 +313,11 @@
         SystemProperties.set(DNS_DOMAIN_SUFFICES, mOriginalDomainSuffices);
     }
 
+    private void setState(VpnState newState) {
+        mState = newState;
+        broadcastConnectivity(newState);
+    }
+
     private void broadcastConnectivity(VpnState s) {
         VpnManager m = new VpnManager(mContext);
         Throwable err = mError;
@@ -319,6 +328,9 @@
             } else if (err instanceof VpnConnectingError) {
                 m.broadcastConnectivity(mProfile.getName(), s,
                         ((VpnConnectingError) err).getErrorCode());
+            } else if (VPN_IS_UP.equals(SystemProperties.get(VPN_STATUS))) {
+                m.broadcastConnectivity(mProfile.getName(), s,
+                        VpnManager.VPN_ERROR_CONNECTION_LOST);
             } else {
                 m.broadcastConnectivity(mProfile.getName(), s,
                         VpnManager.VPN_ERROR_CONNECTION_FAILED);
@@ -366,7 +378,7 @@
     // returns false if vpn connectivity is broken
     private boolean checkConnectivity() {
         if (mDaemonHelper.anyDaemonStopped() || isLocalIpChanged()) {
-            onDisconnect();
+            onError(new IOException("Connectivity lost"));
             return false;
         } else {
             return true;
diff --git a/vpn/java/android/net/vpn/VpnManager.java b/vpn/java/android/net/vpn/VpnManager.java
index e448e5a..f71bbea 100644
--- a/vpn/java/android/net/vpn/VpnManager.java
+++ b/vpn/java/android/net/vpn/VpnManager.java
@@ -54,6 +54,8 @@
     public static final int VPN_ERROR_CHALLENGE = 4;
     /** Error code to indicate an error of remote server hanging up. */
     public static final int VPN_ERROR_REMOTE_HUNG_UP = 5;
+    /** Error code to indicate an error of losing connectivity. */
+    public static final int VPN_ERROR_CONNECTION_LOST = 6;
     private static final int VPN_ERROR_NO_ERROR = 0;
 
     public static final String PROFILES_PATH = "/data/misc/vpn/profiles";