Set isConnected, isBound, implCreated on server-side LocalSockets

Previously LocalServerSocket.accept() would return a LocalSocket
instance with isConnected, isBound and implCreated set to false.
[implCreated determines whether impl.create() needs to called].

A socket created via accept() in this way is implicitly bound
and connected. impl.create() does not need to be called because
impl.accept(LocalSocketImpl s) is called instead and has the same
effect (s.fd and s.mFdCreatedInternally set correctly).

This change modifies the behavior so that the flags are now all
set to true in this case and isBound() and isConnected() will
now return the correct answer.

Attempts to call bind() and connect() will still throw
IOException as before, but with a different exception message.

Correctly setting implCreated in LocalSocket means that
LocalSocketImpl.create() will no longer be called for accept()
created sockets and no longer needs to treat the "fd != null"
case as a no-op: we can now assert that there must be no fd set
when create() is called as we will no longer call it with sockets
created using accept().

Bug: https://code.google.com/p/android/issues/detail?id=35942
Test: Device boot
Test: vogar --mode app_process cts/tests/tests/net/src/android/net/cts/LocalServerSocketTest.java
Test: vogar --mode app_process cts/tests/tests/net/src/android/net/cts/LocalSocketTest.java
Change-Id: I3ac55439412e84501ae7c5ae6c9976e03b2d6fc5
diff --git a/core/java/android/net/LocalServerSocket.java b/core/java/android/net/LocalServerSocket.java
index 9464222..e1eaf00 100644
--- a/core/java/android/net/LocalServerSocket.java
+++ b/core/java/android/net/LocalServerSocket.java
@@ -87,9 +87,9 @@
     {
         LocalSocketImpl acceptedImpl = new LocalSocketImpl();
 
-        impl.accept (acceptedImpl);
+        impl.accept(acceptedImpl);
 
-        return new LocalSocket(acceptedImpl, LocalSocket.SOCKET_UNKNOWN);
+        return LocalSocket.createLocalSocketForAccept(acceptedImpl, LocalSocket.SOCKET_UNKNOWN);
     }
 
     /**
diff --git a/core/java/android/net/LocalSocket.java b/core/java/android/net/LocalSocket.java
index e14facb1..3f8d9d3 100644
--- a/core/java/android/net/LocalSocket.java
+++ b/core/java/android/net/LocalSocket.java
@@ -75,17 +75,24 @@
         isConnected = true;
     }
 
-    /**
-     * for use with AndroidServerSocket
-     * @param impl a SocketImpl
-     */
-    /*package*/ LocalSocket(LocalSocketImpl impl, int sockType) {
+    private LocalSocket(LocalSocketImpl impl, int sockType) {
         this.impl = impl;
         this.sockType = sockType;
         this.isConnected = false;
         this.isBound = false;
     }
 
+    /**
+     * for use with LocalServerSocket.accept()
+     */
+    static LocalSocket createLocalSocketForAccept(LocalSocketImpl impl, int sockType) {
+        LocalSocket socket = new LocalSocket(impl, sockType);
+        socket.isConnected = true;
+        socket.isBound = true;
+        socket.implCreated = true;
+        return socket;
+    }
+
     /** {@inheritDoc} */
     @Override
     public String toString() {
diff --git a/core/java/android/net/LocalSocketImpl.java b/core/java/android/net/LocalSocketImpl.java
index 0f0e9c4..d8f7821 100644
--- a/core/java/android/net/LocalSocketImpl.java
+++ b/core/java/android/net/LocalSocketImpl.java
@@ -235,29 +235,29 @@
      * @throws IOException
      */
     public void create(int sockType) throws IOException {
-        // no error if socket already created
-        // need this for LocalServerSocket.accept()
-        if (fd == null) {
-            int osType;
-            switch (sockType) {
-                case LocalSocket.SOCKET_DGRAM:
-                    osType = OsConstants.SOCK_DGRAM;
-                    break;
-                case LocalSocket.SOCKET_STREAM:
-                    osType = OsConstants.SOCK_STREAM;
-                    break;
-                case LocalSocket.SOCKET_SEQPACKET:
-                    osType = OsConstants.SOCK_SEQPACKET;
-                    break;
-                default:
-                    throw new IllegalStateException("unknown sockType");
-            }
-            try {
-                fd = Os.socket(OsConstants.AF_UNIX, osType, 0);
-                mFdCreatedInternally = true;
-            } catch (ErrnoException e) {
-                e.rethrowAsIOException();
-            }
+        if (fd != null) {
+            throw new IOException("LocalSocketImpl already has an fd");
+        }
+
+        int osType;
+        switch (sockType) {
+            case LocalSocket.SOCKET_DGRAM:
+                osType = OsConstants.SOCK_DGRAM;
+                break;
+            case LocalSocket.SOCKET_STREAM:
+                osType = OsConstants.SOCK_STREAM;
+                break;
+            case LocalSocket.SOCKET_SEQPACKET:
+                osType = OsConstants.SOCK_SEQPACKET;
+                break;
+            default:
+                throw new IllegalStateException("unknown sockType");
+        }
+        try {
+            fd = Os.socket(OsConstants.AF_UNIX, osType, 0);
+            mFdCreatedInternally = true;
+        } catch (ErrnoException e) {
+            e.rethrowAsIOException();
         }
     }