Exemplo n.º 1
0
 bool?IsWifiDirectGroupOwner(AndroidDevice device)
 // Is this guy the group owner of a Wifi Direct Group?
 {
     try {
         // Example response:
         //  p2p0: ip 192.168.49.1 mask 255.255.255.0 flags [up broadcast running multicast]
         CommandResultReceiver rcvr = new CommandResultReceiver();
         AdbHelper.Instance.ExecuteRemoteCommand(AndroidDebugBridge.AdbServerSocketAddress, "ifconfig p2p0", device.SerialNumbers[0], rcvr);
         string regex = $"p2p0: ip ({Device.RegExIpAddr}) mask {Device.RegExIpAddr} flags \\[([a-zA-Z ]*)\\]";
         Match  match = Regex.Match(rcvr.Result, regex, RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline);
         if (match.Success && match.Groups[1].Value == AndroidDevice.WifiDirectIPAddress.ToString())
         {
             string[] splits = match.Groups[2].Value.ToLowerInvariant().Split(' ');
             if (splits.Contains("up"))
             {
                 return(true);
             }
         }
     }
     catch (Exception)
     {
         return(null);
     }
     return(false);
 }
Exemplo n.º 2
0
        public AndroidDevice DisconnectedCopy()
        {
            AndroidDevice result = (AndroidDevice)this.MemberwiseClone();

            result.database = null;
            return(result);
        }
Exemplo n.º 3
0
        void ReconnectToLastTCPIPDevice()
        // Attempt to reconnect to the TCPIP device we last saw
        {
            lock (this.deviceConnectionLock)
            {
                if (this.lastTPCIPConnected != null)
                {
                    string ipAddress  = this.lastTPCIPConnected.IPAddressLastConnected ?? this.lastTPCIPConnected.WlanIpAddress;
                    int    portNumber = adbdPort;

                    this.tracer.Trace($"   reconnecting to {this.lastTPCIPConnected.UserIdentifier}:{this.lastTPCIPConnected.USBSerialNumber} on {ipAddress}");
                    if (AdbHelper.Instance.Connect(AndroidDebugBridge.AdbServerSocketAddress, ipAddress, portNumber))
                    {
                        // Ok, we connected. But is it the same guy? We'll have to check later. We
                        // snarf away a copy of the device so we'll be able to compare it's current
                        // state to what we find later; if we didn't copy, then this state could be
                        // tarnished by the 'update to latest connected devices' step.
                        NotifyReconnected(Resources.NotifyReconnected, this.lastTPCIPConnected.UserIdentifier, ipAddress);
                        this.reconnectionToVerify = this.lastTPCIPConnected.DisconnectedCopy();
                        this.lastTPCIPConnected.IPAddressLastConnected = ipAddress;
                    }
                    else
                    {
                        NotifyReconnected(Resources.NotifyReconnectedFail, this.lastTPCIPConnected.UserIdentifier, ipAddress);
                        this.lastTPCIPConnected.IPAddressLastConnected = null;
                    }
                }
            }
        }
Exemplo n.º 4
0
 void RememberLastTCPIPDevice(AndroidDevice device, string ipAddress)
 {
     lock (this.deviceConnectionLock)
     {
         device.IPAddressLastConnected = ipAddress;
         this.lastTPCIPConnected       = device;
         UpdateTrayStatus();
     }
 }
Exemplo n.º 5
0
 void ForgetLastTCPIPDevice()
 {
     lock (this.deviceConnectionLock)
     {
         if (this.lastTPCIPConnected != null)
         {
             this.lastTPCIPConnected = null;
             UpdateTrayStatus();
         }
     }
 }
Exemplo n.º 6
0
        bool SendTcpipCommandAndConnect(AndroidDevice device, string ipAddress)
        {
            bool result = false;

            bool tcpipIssuedOk = true;

            try {
                // Restart the device listening on a port of interest. We don't know if he got there,
                // as we get no response from the command issued.
                this.tracer.Trace($"   restarting {device.USBSerialNumber} adbd in TCPIP at {ipAddress}");
                AdbHelper.Instance.TcpIp(AndroidDebugBridge.AdbServerSocketAddress, device.USBSerialNumber, adbdPort);
            }
            catch (Exception)
            {
                this.tracer.Trace($"   restart of {device.USBSerialNumber} adbd failed");
                tcpipIssuedOk = false;
            }

            if (tcpipIssuedOk)
            {
                // Give it a chance to restart. The actual time used here is a total guess, but
                // it does seem to work. Mostly (?).
                Thread.Sleep(1000);

                // Connect to the TCPIP version of that device
                this.tracer.Trace($"   connecting to restarted {ipAddress} device");
                if (AdbHelper.Instance.Connect(AndroidDebugBridge.AdbServerSocketAddress, ipAddress, adbdPort))
                {
                    NotifyConnected(device, ipAddress);

                    // Remember to whom we last connected for later ADB Server restarts
                    RememberLastTCPIPDevice(device, ipAddress);
                    result = true;
                }
            }

            if (!result)
            {
                this.tracer.Trace($"   failed to connect to {ipAddress}:{adbdPort}");
                NotifyDisconnected(device, ipAddress);
                device.IPAddressLastConnected = null;
            }

            return(result);
        }
Exemplo n.º 7
0
        //-----------------------------------------------------------------------------------------
        // Operations
        //-----------------------------------------------------------------------------------------

        public AndroidDevice FromUSBSerialNumber(string usbSerialNumber)
        {
            if (string.IsNullOrEmpty(usbSerialNumber))
            {
                throw new System.ArgumentException($"'{nameof(usbSerialNumber)}' cannot be null or empty");
            }

            AndroidDevice result;

            if (!this.mpUsbToDevice.TryGetValue(usbSerialNumber, out result))
            {
                result = new AndroidDevice(this)
                {
                    USBSerialNumber = usbSerialNumber
                };
                this.mpUsbToDevice[usbSerialNumber] = result;
            }
            return(result);
        }
Exemplo n.º 8
0
        public void UpdateFromDevicesConnectedToAdbServer(List <Device> devices)
        {
            foreach (AndroidDevice ad in this.mpUsbToDevice.Values)
            {
                ad.IsConnected   = false;
                ad.IsTCPIPOnLine = false;
                ad.AdbEndpoints  = new List <IPEndPoint>();
                ad.SerialNumbers = new List <string>();
            }

            foreach (Device device in devices)
            {
                if (!string.IsNullOrEmpty(device.USBSerialNumber))
                {
                    AndroidDevice ad = FromUSBSerialNumber(device.USBSerialNumber);
                    ad.IsConnected    = true;
                    ad.WifiDirectName = device.WifiDirectName;
                    ad.WlanIpAddress  = device.WlanIpAddress;
                    ad.WlanIsRunning  = device.WlanIsRunning;
                    ad.SerialNumbers.Add(device.SerialNumber);

                    if (device.SerialNumberIsTCPIP)
                    {
                        string[] pieces = device.SerialNumber.Split(':');
                        ad.AdbEndpoints.Add(new IPEndPoint(IPAddress.Parse(pieces[0]), int.Parse(pieces[1])));
                        ad.IsTCPIPOnLine = device.IsOnline;
                    }
                }
                else
                {
                    // We're hitting this occasionally, but we don't exactly know why. It seems like
                    // the Win32 notifications might be racing with the ADB server notifications: this
                    // only showed up on Bob's new super-duper-fast desktop.
                    //
                    // We really ought to track down what's happening. But for now, we'll just disable
                    // the USB-notification path, which was always redundant, anyway.
                }
            }
        }
Exemplo n.º 9
0
 void NotifyConnected(AndroidDevice device, string ipAddress)
     {
     string format = ipAddress==AndroidDevice.WifiDirectIPAddress.ToString() ? Resources.NotifyConnectedWifiDirect : Resources.NotifyConnected;
     NotifyConnectedMessage(format, device, ipAddress);
     }
Exemplo n.º 10
0
 void NotifyNotPingable(AndroidDevice device)
     {
     NotifyMessage(string.Format(Resources.NotifyNotPingable, device.UserIdentifier, device.WlanIpAddress));
     }
Exemplo n.º 11
0
 void NotifyWifiNotRunning(AndroidDevice device)
     {
     NotifyMessage(string.Format(Resources.NotifyWifiOff, device.UserIdentifier, device.WlanIpAddress));
     }
Exemplo n.º 12
0
        void ReconnectToLastTCPIPDevice()
        // Attempt to reconnect to the TCPIP device we last saw
            {
            lock (this.deviceConnectionLock)
                {
                if (this.lastTPCIPConnected != null)
                    {
                    string ipAddress = this.lastTPCIPConnected.IPAddressLastConnected ?? this.lastTPCIPConnected.WlanIpAddress;
                    int portNumber   = adbdPort;

                    this.tracer.Trace($"   reconnecting to {this.lastTPCIPConnected.UserIdentifier}:{this.lastTPCIPConnected.USBSerialNumber} on {ipAddress}");
                    if (AdbHelper.Instance.Connect(AndroidDebugBridge.AdbServerSocketAddress, ipAddress, portNumber))
                        {
                        // Ok, we connected. But is it the same guy? We'll have to check later. We
                        // snarf away a copy of the device so we'll be able to compare it's current 
                        // state to what we find later; if we didn't copy, then this state could be
                        // tarnished by the 'update to latest connected devices' step.
                        NotifyReconnected(Resources.NotifyReconnected, this.lastTPCIPConnected.UserIdentifier, ipAddress);
                        this.reconnectionToVerify = this.lastTPCIPConnected.DisconnectedCopy();
                        this.lastTPCIPConnected.IPAddressLastConnected = ipAddress;
                        }
                    else
                        {
                        NotifyReconnected(Resources.NotifyReconnectedFail, this.lastTPCIPConnected.UserIdentifier, ipAddress);
                        this.lastTPCIPConnected.IPAddressLastConnected = null;
                        }
                    }
                }
            }
Exemplo n.º 13
0
        bool SendTcpipCommandAndConnect(AndroidDevice device, string ipAddress)
            {
            bool result = false;

            bool tcpipIssuedOk = true;
            try {
                // Restart the device listening on a port of interest. We don't know if he got there,
                // as we get no response from the command issued.
                this.tracer.Trace($"   restarting {device.USBSerialNumber} adbd in TCPIP at {ipAddress}");
                AdbHelper.Instance.TcpIp(AndroidDebugBridge.AdbServerSocketAddress, device.USBSerialNumber, adbdPort);
                }
            catch (Exception)
                {
                this.tracer.Trace($"   restart of {device.USBSerialNumber} adbd failed");
                tcpipIssuedOk = false;
                }
                    
            if (tcpipIssuedOk)
                {
                // Give it a chance to restart. The actual time used here is a total guess, but
                // it does seem to work. Mostly (?).
                Thread.Sleep(1000);

                // Connect to the TCPIP version of that device
                this.tracer.Trace($"   connecting to restarted {ipAddress} device");
                if (AdbHelper.Instance.Connect(AndroidDebugBridge.AdbServerSocketAddress, ipAddress, adbdPort))
                    {
                    NotifyConnected(device, ipAddress);

                    // Remember to whom we last connected for later ADB Server restarts
                    RememberLastTCPIPDevice(device, ipAddress);
                    result = true;
                    }
                }
            
            if (!result)
                {
                this.tracer.Trace($"   failed to connect to {ipAddress}:{adbdPort}");
                NotifyDisconnected(device, ipAddress);
                device.IPAddressLastConnected = null;
                }

            return result;
            }
Exemplo n.º 14
0
 void NotifyNotPingable(AndroidDevice device)
 {
     NotifyMessage(string.Format(Resources.NotifyNotPingable, device.UserIdentifier, device.WlanIpAddress));
 }
Exemplo n.º 15
0
        bool?EnsureUSBConnectedDevicesAreOnTCPIP(string reason)
        // Iterate over all the extant Android devices (that ADB knows about) and make sure that each
        // one of them is listening on TCPIP. This method is idempotent, so you can call it as often
        // and as frequently as you like. Answer as to whether there were any devices known about by
        // the ADB server.
        {
            // Don't actually do anything if the user has asked us not to
            if (!this.armed)
            {
                return(null);
            }

            bool serverKnowsAboutAnyDevices = false;

            // We synchronize for paranoid reasons: we're not SURE we can be be called on
            // a whole range of threads, possibly simultaneously, but why take the chance?
            lock (this.deviceConnectionLock)
            {
                this.tracer.Trace($"v-----EnsureAdbDevicesAreOnTCPIP({reason})-----v");

                // Get ourselves the list of devices that ADB currently knows about
                List <Device> devicesConnectedToAdbServer = AdbHelper.Instance.GetDevices(AndroidDebugBridge.AdbServerSocketAddress);
                this.androidDeviceDatabase.UpdateFromDevicesConnectedToAdbServer(devicesConnectedToAdbServer);

                // Do a bit of tracing
                foreach (Device device in devicesConnectedToAdbServer)
                {
                    this.tracer.Trace($"   usb:{device.USBSerialNumber} ipAddress:{device.WlanIpAddress} wifi:{(device.WlanIsRunning?"on":"off")} serial:{device.SerialNumber}");
                }
                this.tracer.Trace($"---------------------------------");
                foreach (AndroidDevice device in this.androidDeviceDatabase.ConnectedDevices)
                {
                    this.tracer.Trace($"   usb:{device.USBSerialNumber} ipAddress:{device.WlanIpAddress} wifi:{(device.WlanIsRunning?"on":"off")} connected:{device.IsAdbConnectedOnTcpip}");
                }

                // Iterate over what's currently connected to ADB
                //
                AndroidDevice potentialLastDevice = null;
                bool          connectedAny        = false;
                bool          wifiDirectAddrInUse = this.androidDeviceDatabase.IsWifiDirectIPAddressConnected;
                foreach (AndroidDevice device in this.androidDeviceDatabase.ConnectedDevices)
                {
                    // Yes, the server knows about some devices
                    serverKnowsAboutAnyDevices = true;

                    if (device.IsAdbConnectedOnTcpip)
                    {
                        // ADB has a TCPIP connection for him; we're not going to add one
                        //
                        potentialLastDevice = potentialLastDevice ?? device;

                        if (this.reconnectionToVerify != null)
                        {
                            // Is this the address we reconnected on?
                            if (this.reconnectionToVerify.WlanIpAddress == device.WlanIpAddress)
                            {
                                // Did we reconnect to the same device?
                                if (this.reconnectionToVerify.USBSerialNumber == device.USBSerialNumber)
                                {
                                    // All is well
                                    this.tracer.Trace($"   verify reconnected: all good: {this.reconnectionToVerify.WlanIpAddress} is still {device.USBSerialNumber}");
                                }
                                else
                                {
                                    // We reconnected to him, but he's the wrong guy. Disconnect.
                                    this.tracer.Trace($"   verify reconnected: fail: {this.reconnectionToVerify.WlanIpAddress}: got: {device.USBSerialNumber} expected: {this.reconnectionToVerify.USBSerialNumber}; disconnecting");
                                    AdbHelper.Instance.Disconnect(AndroidDebugBridge.AdbServerSocketAddress, device.WlanIpAddress, adbdPort);
                                    NotifyReconnected(Resources.NotifyReconnectedFail, device.UserIdentifier, device.WlanIpAddress);

                                    // If we're *still* porentially reconnecting to that same guy, stop that
                                    if (this.lastTPCIPConnected != null && this.lastTPCIPConnected.USBSerialNumber == this.reconnectionToVerify.USBSerialNumber)
                                    {
                                        ForgetLastTCPIPDevice();
                                    }

                                    // And he's no longer a potential *later* reconnection
                                    if (potentialLastDevice == device)
                                    {
                                        potentialLastDevice = null;
                                    }
                                }

                                // Verification of reconnection is complete
                                this.reconnectionToVerify = null;
                            }
                        }
                    }
                    else
                    {
                        // ADB doesn't already have a TCPIP connection for him. We'll try to make one if we can.
                        //
                        // Can we reach him over WifiDirect?
                        if (!wifiDirectAddrInUse &&
                            IsPingable(AndroidDevice.WifiDirectIPAddress) &&
                            (IsWifiDirectGroupOwner(device) ?? false) &&
                            SendTcpipCommandAndConnect(device, AndroidDevice.WifiDirectIPAddress))
                        {
                            this.tracer.Trace($"connected to {device.UserIdentifier} over WifiDirect!");
                            wifiDirectAddrInUse = true;
                            connectedAny        = true;
                        }
                        else if (string.IsNullOrEmpty(device.WlanIpAddress))
                        {
                            NotifyNoIpAddress(device);
                        }
                        else if (!device.WlanIsRunning)
                        {
                            NotifyWifiNotRunning(device);
                        }
                        else
                        {
                            // He's not already connected on an IP network. But can we reach him?
                            if (IsPingable(device.WlanIpAddress))
                            {
                                // Connect to him
                                if (SendTcpipCommandAndConnect(device, device.WlanIpAddress))
                                {
                                    connectedAny = true;
                                }
                            }
                            else
                            {
                                NotifyNotPingable(device);
                            }
                        }
                    }
                }

                // If we didn't do any connection here, remember something that ADB is ALREADY
                // connected to as a potential reconnection target for later
                if (!connectedAny && potentialLastDevice != null)
                {
                    RememberLastTCPIPDevice(potentialLastDevice, potentialLastDevice.IPAddressLastConnected ?? potentialLastDevice.WlanIpAddress);
                }

                this.tracer.Trace($"^-----EnsureAdbDevicesAreOnTCPIP({reason})-----^");
            }

            return(serverKnowsAboutAnyDevices);
        }
Exemplo n.º 16
0
 bool SendTcpipCommandAndConnect(AndroidDevice device, IPAddress ipAddress)
 {
     return(SendTcpipCommandAndConnect(device, ipAddress.ToString()));
 }
Exemplo n.º 17
0
 void RememberLastTCPIPDevice(AndroidDevice device, string ipAddress)
     {
     lock (this.deviceConnectionLock)
         {
         device.IPAddressLastConnected = ipAddress;
         this.lastTPCIPConnected = device;
         UpdateTrayStatus();
         }
     }
Exemplo n.º 18
0
 void NotifyConnectedMessage(string format, AndroidDevice device, string ipAddress)
 {
     NotifyMessage(string.Format(format, device.UserIdentifier, ipAddress));
 }
Exemplo n.º 19
0
        void NotifyDisconnected(AndroidDevice device, string ipAddress)
        {
            string format = Resources.NotifyConnectedFail;

            NotifyConnectedMessage(format, device, ipAddress);
        }
Exemplo n.º 20
0
        void NotifyConnected(AndroidDevice device, string ipAddress)
        {
            string format = ipAddress == AndroidDevice.WifiDirectIPAddress.ToString() ? Resources.NotifyConnectedWifiDirect : Resources.NotifyConnected;

            NotifyConnectedMessage(format, device, ipAddress);
        }
Exemplo n.º 21
0
 void NotifyDisconnected(AndroidDevice device, string ipAddress)
     {
     string format = Resources.NotifyConnectedFail;
     NotifyConnectedMessage(format, device, ipAddress);
     }
Exemplo n.º 22
0
 bool? IsWifiDirectGroupOwner(AndroidDevice device)
 // Is this guy the group owner of a Wifi Direct Group?
     {
     try {
         // Example response:
         //  p2p0: ip 192.168.49.1 mask 255.255.255.0 flags [up broadcast running multicast]
         CommandResultReceiver rcvr = new CommandResultReceiver();
         AdbHelper.Instance.ExecuteRemoteCommand(AndroidDebugBridge.AdbServerSocketAddress, "ifconfig p2p0", device.SerialNumbers[0], rcvr);
         string regex=$"p2p0: ip ({Device.RegExIpAddr}) mask {Device.RegExIpAddr} flags \\[([a-zA-Z ]*)\\]";
         Match match = Regex.Match(rcvr.Result, regex, RegexOptions.Compiled|RegexOptions.IgnoreCase|RegexOptions.Singleline);
         if (match.Success && match.Groups[1].Value==AndroidDevice.WifiDirectIPAddress.ToString())
             {
             string[] splits = match.Groups[2].Value.ToLowerInvariant().Split(' ');
             if (splits.Contains("up"))
                 {
                 return true;
                 }
             }
         }
     catch (Exception)
         {
         return null;
         }
     return false;
     }
Exemplo n.º 23
0
 void NotifyConnectedMessage(string format, AndroidDevice device, string ipAddress)
     {
     NotifyMessage(string.Format(format, device.UserIdentifier, ipAddress));
     }
Exemplo n.º 24
0
 bool SendTcpipCommandAndConnect(AndroidDevice device, IPAddress ipAddress)
     {
     return SendTcpipCommandAndConnect(device, ipAddress.ToString());
     }
Exemplo n.º 25
0
 void ForgetLastTCPIPDevice()
     {
     lock (this.deviceConnectionLock)
         {
         if (this.lastTPCIPConnected != null)
             {
             this.lastTPCIPConnected = null;
             UpdateTrayStatus();
             }
         }            
     }
Exemplo n.º 26
0
 void NotifyWifiNotRunning(AndroidDevice device)
 {
     NotifyMessage(string.Format(Resources.NotifyWifiOff, device.UserIdentifier, device.WlanIpAddress));
 }
Exemplo n.º 27
0
        //-----------------------------------------------------------------------------------------
        // Operations
        //-----------------------------------------------------------------------------------------
        public AndroidDevice FromUSBSerialNumber(string usbSerialNumber)
        {
            if (string.IsNullOrEmpty(usbSerialNumber))
                throw new System.ArgumentException($"'{nameof(usbSerialNumber)}' cannot be null or empty");

            AndroidDevice result;
            if (!this.mpUsbToDevice.TryGetValue(usbSerialNumber, out result))
                {
                result = new AndroidDevice(this) { USBSerialNumber = usbSerialNumber };
                this.mpUsbToDevice[usbSerialNumber] = result;
                }
            return result;
        }
Exemplo n.º 28
0
        bool? EnsureUSBConnectedDevicesAreOnTCPIP(string reason)
        // Iterate over all the extant Android devices (that ADB knows about) and make sure that each
        // one of them is listening on TCPIP. This method is idempotent, so you can call it as often
        // and as frequently as you like. Answer as to whether there were any devices known about by
        // the ADB server.
            {
            // Don't actually do anything if the user has asked us not to
            if (!this.armed)
                return null;

            bool serverKnowsAboutAnyDevices = false;

            // We synchronize for paranoid reasons: we're not SURE we can be be called on
            // a whole range of threads, possibly simultaneously, but why take the chance?
            lock (this.deviceConnectionLock)
                {
                this.tracer.Trace($"v-----EnsureAdbDevicesAreOnTCPIP({reason})-----v");

                // Get ourselves the list of devices that ADB currently knows about
                List<Device> devicesConnectedToAdbServer = AdbHelper.Instance.GetDevices(AndroidDebugBridge.AdbServerSocketAddress);
                this.androidDeviceDatabase.UpdateFromDevicesConnectedToAdbServer(devicesConnectedToAdbServer);

                // Do a bit of tracing
                foreach (Device device in devicesConnectedToAdbServer)
                    {
                    this.tracer.Trace($"   usb:{device.USBSerialNumber} ipAddress:{device.WlanIpAddress} wifi:{(device.WlanIsRunning?"on":"off")} serial:{device.SerialNumber}");
                    }
                this.tracer.Trace($"---------------------------------");
                foreach (AndroidDevice device in this.androidDeviceDatabase.ConnectedDevices)
                    {
                    this.tracer.Trace($"   usb:{device.USBSerialNumber} ipAddress:{device.WlanIpAddress} wifi:{(device.WlanIsRunning?"on":"off")} connected:{device.IsAdbConnectedOnTcpip}");
                    }

                // Iterate over what's currently connected to ADB
                // 
                AndroidDevice potentialLastDevice = null;
                bool          connectedAny        = false;
                bool          wifiDirectAddrInUse = this.androidDeviceDatabase.IsWifiDirectIPAddressConnected;
                foreach (AndroidDevice device in this.androidDeviceDatabase.ConnectedDevices)
                    {
                    // Yes, the server knows about some devices
                    serverKnowsAboutAnyDevices = true;

                    if (device.IsAdbConnectedOnTcpip)
                        {
                        // ADB has a TCPIP connection for him; we're not going to add one
                        // 
                        potentialLastDevice = potentialLastDevice ?? device;

                        if (this.reconnectionToVerify != null)
                            {
                            // Is this the address we reconnected on?
                            if (this.reconnectionToVerify.WlanIpAddress == device.WlanIpAddress)
                                {
                                // Did we reconnect to the same device?
                                if (this.reconnectionToVerify.USBSerialNumber == device.USBSerialNumber)
                                    {
                                    // All is well
                                    this.tracer.Trace($"   verify reconnected: all good: {this.reconnectionToVerify.WlanIpAddress} is still {device.USBSerialNumber}");
                                    }
                                else
                                    {
                                    // We reconnected to him, but he's the wrong guy. Disconnect.
                                    this.tracer.Trace($"   verify reconnected: fail: {this.reconnectionToVerify.WlanIpAddress}: got: {device.USBSerialNumber} expected: {this.reconnectionToVerify.USBSerialNumber}; disconnecting");
                                    AdbHelper.Instance.Disconnect(AndroidDebugBridge.AdbServerSocketAddress, device.WlanIpAddress, adbdPort);
                                    NotifyReconnected(Resources.NotifyReconnectedFail, device.UserIdentifier, device.WlanIpAddress);
                                    
                                    // If we're *still* porentially reconnecting to that same guy, stop that
                                    if (this.lastTPCIPConnected != null && this.lastTPCIPConnected.USBSerialNumber == this.reconnectionToVerify.USBSerialNumber)
                                        {
                                        ForgetLastTCPIPDevice();
                                        }

                                    // And he's no longer a potential *later* reconnection
                                    if (potentialLastDevice == device)
                                        potentialLastDevice = null;                                    
                                    }
                                
                                // Verification of reconnection is complete
                                this.reconnectionToVerify = null;    
                                }
                            }
                        }
                    else
                        {
                        // ADB doesn't already have a TCPIP connection for him. We'll try to make one if we can.
                        //
                        // Can we reach him over WifiDirect?
                        if (!wifiDirectAddrInUse 
                                && IsPingable(AndroidDevice.WifiDirectIPAddress) 
                                && (IsWifiDirectGroupOwner(device) ?? false)
                                && SendTcpipCommandAndConnect(device, AndroidDevice.WifiDirectIPAddress))
                            {
                            this.tracer.Trace($"connected to {device.UserIdentifier} over WifiDirect!");
                            wifiDirectAddrInUse = true;
                            connectedAny = true;
                            }
                        else if (string.IsNullOrEmpty(device.WlanIpAddress))
                            {
                            NotifyNoIpAddress(device);
                            }
                        else if (!device.WlanIsRunning)
                            {
                            NotifyWifiNotRunning(device);    
                            }
                        else
                            {
                            // He's not already connected on an IP network. But can we reach him?
                            if (IsPingable(device.WlanIpAddress))
                                {
                                // Connect to him
                                if (SendTcpipCommandAndConnect(device, device.WlanIpAddress))
                                    {
                                    connectedAny = true;
                                    }
                                }
                            else
                                NotifyNotPingable(device);
                            }
                        }
                    }

                // If we didn't do any connection here, remember something that ADB is ALREADY
                // connected to as a potential reconnection target for later
                if (!connectedAny && potentialLastDevice != null)
                    {
                    RememberLastTCPIPDevice(potentialLastDevice, potentialLastDevice.IPAddressLastConnected ?? potentialLastDevice.WlanIpAddress);
                    }

               this.tracer.Trace($"^-----EnsureAdbDevicesAreOnTCPIP({reason})-----^"); 
               }

            return serverKnowsAboutAnyDevices;
            }