OSDN Git Service

auto import from //depot/cupcake/@132589
[android-x86/packages-apps-IM.git] / src / com / android / im / imps / ImpsConnection.java
index bed94cf..8f84cdb 100644 (file)
@@ -32,6 +32,7 @@ import com.android.im.engine.LoginInfo;
 import com.android.im.engine.Presence;
 import com.android.im.imps.ImpsConnectionConfig.CirMethod;
 import com.android.im.imps.ImpsConnectionConfig.TransportType;
+import com.android.im.imps.Primitive.TransactionMode;
 
 /**
  * An implementation of ImConnection of Wireless Village IMPS protocol.
@@ -126,15 +127,27 @@ public class ImpsConnection extends ImConnection {
         if (!checkAndSetState(SUSPENDED)) {
             return;
         }
-
-        mReestablishing = true;
-        try {
-            mSession = new ImpsSession(this, cookie);
-        } catch (ImException e) {
-            setState(DISCONNECTED, e.getImError());
-            return;
+        // If we can resume from the data channel, which means the
+        // session is still valid, we can just re-use the existing
+        // session and don't need to re-establish it.
+        if (mDataChannel.resume()) {
+            try {
+                setupCIRChannel();
+            } catch(ImException e) {}
+            setState(LOGGED_IN, null);
+        } else {
+            // Failed to resume the data channel which means the
+            // session might have expired, we need to re-establish
+            // the session by signing in again.
+            mReestablishing = true;
+            try {
+                mSession = new ImpsSession(this, cookie);
+            } catch (ImException e) {
+                setState(DISCONNECTED, e.getImError());
+                return;
+            }
+            doLogin();
         }
-        doLogin();
     }
 
     @Override
@@ -154,7 +167,11 @@ public class ImpsConnection extends ImConnection {
 
     private void doLogin() {
         try {
-            initDataChannel();
+            if (mConfig.useSmsAuth()) {
+                mDataChannel = new SmsDataChannel(this);
+            } else {
+                mDataChannel = createDataChannel();
+            }
             mDataChannel.connect();
         } catch (ImException e) {
             ImErrorInfo error = e.getImError();
@@ -284,6 +301,34 @@ public class ImpsConnection extends ImConnection {
         }
 
         private void onAuthenticated() {
+            // The user has chosen logout before the session established, just
+            // send the Logout-Request in this case.
+            if (mState == LOGGING_OUT) {
+                sendLogoutRequest();
+                return;
+            }
+
+            if (mConfig.useSmsAuth()
+                    && mConfig.getDataChannelBinding() != TransportType.SMS) {
+                // SMS data channel was used if it's set to send authentication
+                // over SMS. Switch to the config data channel after authentication
+                // completed.
+                try {
+                    DataChannel dataChannel = createDataChannel();
+                    dataChannel.connect();
+
+                    mDataChannel.shutdown();
+                    mDataChannel = dataChannel;
+                    mDispatcherThread.changeDataChannel(dataChannel);
+                } catch (ImException e) {
+                    // This should not happen since only http data channel which
+                    // does not do the real network connection in connect() is
+                    // valid here now.
+                    logoutAsync();
+                    return;
+                }
+            }
+
             if(mSession.isCapablityRequestRequired()) {
                 mSession.negotiateCapabilityAsync(new AsyncCompletion(){
                     public void onComplete() {
@@ -353,26 +398,31 @@ public class ImpsConnection extends ImConnection {
             mCirChannel = null;
         }
 
-        LogoutCompletion logoutCompletion = new LogoutCompletion();
-        AsyncTransaction tx = new SimpleAsyncTransaction(mTransactionManager,
-                logoutCompletion);
-        Primitive logoutPrimitive = new Primitive(ImpsTags.Logout_Request);
-        tx.sendRequest(logoutPrimitive);
+        // Only send the Logout-Request if the session has been established.
+        if (mSession.getID() != null) {
+            sendLogoutRequest();
+        }
     }
 
-    // We cannot shut down our connections in ImpsAsyncTransaction.onResponse()
-    // because at that time the logout transaction itself hasn't ended yet. So
-    // we have to do this in this completion object.
-    class LogoutCompletion implements AsyncCompletion {
-        public void onComplete() {
-            shutdown();
-        }
+    void sendLogoutRequest() {
+        // We cannot shut down our connections in ImpsAsyncTransaction.onResponse()
+        // because at that time the logout transaction itself hasn't ended yet. So
+        // we have to do this in this completion object.
+        AsyncCompletion completion = new AsyncCompletion() {
+            public void onComplete() {
+                shutdown();
+            }
 
-        public void onError(ImErrorInfo error) {
-            // We simply ignore all errors when logging out.
-            // NowIMP responds a <Disconnect> instead of <Status> on logout request.
-            shutdown();
-        }
+            public void onError(ImErrorInfo error) {
+                // We simply ignore all errors when logging out.
+                // NowIMP responds a <Disconnect> instead of <Status> on logout request.
+                shutdown();
+            }
+        };
+        AsyncTransaction tx = new SimpleAsyncTransaction(mTransactionManager,
+                completion);
+        Primitive logoutPrimitive = new Primitive(ImpsTags.Logout_Request);
+        tx.sendRequest(logoutPrimitive);
     }
 
     public ImpsSession getSession() {
@@ -432,10 +482,12 @@ public class ImpsConnection extends ImConnection {
         mDataChannel.sendPrimitive(pollingRequest);
     }
 
-    private void initDataChannel() throws ImException {
+    private DataChannel createDataChannel() throws ImException {
         TransportType dataChannelBinding = mConfig.getDataChannelBinding();
         if (dataChannelBinding == TransportType.HTTP) {
-            mDataChannel = new HttpDataChannel(this);
+            return new HttpDataChannel(this);
+        } else if (dataChannelBinding == TransportType.SMS) {
+            return new SmsDataChannel(this);
         } else {
             throw new ImException("Unsupported data channel binding");
         }
@@ -461,6 +513,8 @@ public class ImpsConnection extends ImConnection {
             mCirChannel = new HttpCirChannel(this, mDataChannel);
         } else if (cirMethod == CirMethod.STCP) {
             mCirChannel = new TcpCirChannel(this);
+        } else if (cirMethod == CirMethod.SSMS) {
+            mCirChannel = new SmsCirChannel(this);
         } else if (cirMethod == CirMethod.NONE) {
             //Do nothing
         } else {
@@ -483,6 +537,11 @@ public class ImpsConnection extends ImConnection {
             mChannel = channel;
         }
 
+        public void changeDataChannel(DataChannel channel) {
+            mChannel = channel;
+            interrupt();
+        }
+
         @Override
         public void run() {
             Primitive primitive = null;
@@ -544,6 +603,19 @@ public class ImpsConnection extends ImConnection {
             }
         }
 
+        if (primitive.getTransactionMode() == TransactionMode.Response) {
+            ImpsErrorInfo error = ImpsUtils.checkResultError(primitive);
+            if (error != null) {
+                int code = error.getCode();
+                if (code == ImpsErrorInfo.SESSION_EXPIRED
+                        || code == ImpsErrorInfo.FORCED_LOGOUT
+                        || code == ImpsErrorInfo.INVALID_SESSION) {
+                    shutdownOnError(error);
+                    return;
+                }
+            }
+        }
+
         // According to the IMPS spec, only VersionDiscoveryResponse which
         // are not supported now doesn't have a transaction ID.
         if (primitive.getTransactionID() != null) {
@@ -690,11 +762,9 @@ public class ImpsConnection extends ImConnection {
         if (mCirChannel != null) {
             mCirChannel.shutdown();
         }
-        if (mDispatcherThread != null) {
-            mDispatcherThread.shutdown();
-        }
+
         if (mDataChannel != null) {
-            mDataChannel.shutdown();
+            mDataChannel.suspend();
         }
 
         setState(SUSPENDED, null);