Beispiel #1
0
		/// <summary>
		/// tells adb to talk to a specific device
		/// </summary>
		/// <param name="adbChan"> the socket connection to adb </param>
		/// <param name="device"> The device to talk to. </param>
		/// <exception cref="TimeoutException"> in case of timeout on the connection. </exception>
		/// <exception cref="AdbCommandRejectedException"> if adb rejects the command </exception>
		/// <exception cref="IOException"> in case of I/O error on the connection. </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: static void setDevice(java.nio.channels.SocketChannel adbChan, IDevice device) throws TimeoutException, AdbCommandRejectedException, java.io.IOException
		internal static void setDevice(SocketChannel adbChan, IDevice device)
		{
			// if the device is not -1, then we first tell adb we're looking to talk
			// to a specific device
			if (device != null)
			{
				string msg = "host:transport:" + device.serialNumber; //$NON-NLS-1$
				var device_query = formAdbRequest(msg);

				write(adbChan, device_query);

				AdbResponse resp = readAdbResponse(adbChan, false); // readDiagString
				if (resp.okay == false)
				{
					throw new AdbCommandRejectedException(resp.message, true); //errorDuringDeviceSelection
				}
			}
		}
Beispiel #2
0
 /// <summary>
 /// Closes the connection.
 /// </summary>
 public void close()
 {
     if (mChannel != null)
     {
         try
         {
             mChannel.close();
         }
         catch (IOException)
         {
             // nothing to be done really...
         }
         mChannel = null;
     }
 }
Beispiel #3
0
		/// <summary>
		/// Write until all data in "data" is written or the connection fails or times out.
		/// <p/>This uses the default time out value. </summary>
		/// <param name="chan"> the opened socket to write to. </param>
		/// <param name="data"> the buffer to send. </param>
		/// <exception cref="TimeoutException"> in case of timeout on the connection. </exception>
		/// <exception cref="IOException"> in case of I/O error on the connection. </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: static void write(java.nio.channels.SocketChannel chan, byte[] data) throws TimeoutException, java.io.IOException
		internal static void write(SocketChannel chan, byte[] data)
		{
			write(chan, data, -1, DdmPreferences.timeOut);
		}
Beispiel #4
0
		/// <summary>
		/// Write until all data in "data" is written, the optional length is reached,
		/// the timeout expires, or the connection fails. Returns "true" if all
		/// data was written. </summary>
		/// <param name="chan"> the opened socket to write to. </param>
		/// <param name="data"> the buffer to send. </param>
		/// <param name="length"> the length to write or -1 to send the whole buffer. </param>
		/// <param name="timeout"> The timeout value. A timeout of zero means "wait forever". </param>
		/// <exception cref="TimeoutException"> in case of timeout on the connection. </exception>
		/// <exception cref="IOException"> in case of I/O error on the connection. </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: static void write(java.nio.channels.SocketChannel chan, byte[] data, int length, int timeout) throws TimeoutException, java.io.IOException
		internal static void write(SocketChannel chan, byte[] data, int length, int timeout)
		{
			ByteBuffer buf = ByteBuffer.wrap(data, 0, length != -1 ? length : data.Length);
			int numWaits = 0;

			while (buf.position != buf.limit)
			{
				int count;

				count = chan.write(buf);
				if (count < 0)
				{
					Log.d("ddms", "write: channel EOF");
					throw new IOException("channel EOF");
				}
				else if (count == 0)
				{
					// TODO: need more accurate timeout?
					if (timeout != 0 && numWaits * WAIT_TIME > timeout)
					{
						Log.d("ddms", "write: timeout");
						throw new TimeoutException();
					}
					// non-blocking spin
                    Thread.Sleep(WAIT_TIME);
					numWaits++;
				}
				else
				{
					numWaits = 0;
				}
			}
		}
Beispiel #5
0
        /// <summary>
        /// Fills a buffer from a socket. </summary>
        /// <param name="socket"> </param>
        /// <param name="buffer"> </param>
        /// <returns> the content of the buffer as a string, or null if it failed to convert the buffer. </returns>
        /// <exception cref="IOException"> </exception>
        //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
        //ORIGINAL LINE: private String read(java.nio.channels.SocketChannel socket, byte[] buffer) throws java.io.IOException
        private string read(SocketChannel socket, byte[] buffer)
        {
            ByteBuffer buf = ByteBuffer.wrap(buffer, 0, buffer.Length);

            while (buf.position != buf.limit)
            {
                int count;

                count = socket.read(buf);
                if (count < 0)
                {
                    throw new IOException("EOF");
                }
            }

            try
            {
                return buffer.getString(0, buf.position, AdbHelper.DEFAULT_ENCODING);
            }
            catch (ArgumentException)
            {
                // we'll return null below.
            }

            return null;
        }
Beispiel #6
0
		/// <summary>
		/// Reads the response from ADB after a command. </summary>
		/// <param name="chan"> The socket channel that is connected to adb. </param>
		/// <param name="readDiagString"> If true, we're expecting an OKAY response to be
		///      followed by a diagnostic string. Otherwise, we only expect the
		///      diagnostic string to follow a FAIL. </param>
		/// <exception cref="TimeoutException"> in case of timeout on the connection. </exception>
		/// <exception cref="IOException"> in case of I/O error on the connection. </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: static AdbResponse readAdbResponse(java.nio.channels.SocketChannel chan, boolean readDiagString) throws TimeoutException, java.io.IOException
		internal static AdbResponse readAdbResponse(SocketChannel chan, bool readDiagString)
		{

			AdbResponse resp = new AdbResponse();

			var reply = new byte[4];
			read(chan, reply);

			if (isOkay(reply))
			{
				resp.okay = true;
			}
			else
			{
				readDiagString = true; // look for a reason after the FAIL
				resp.okay = false;
			}

			// not a loop -- use "while" so we can use "break"
			try
			{
				while (readDiagString)
				{
					// length string is in next 4 bytes
					var lenBuf = new byte[4];
					read(chan, lenBuf);

					string lenStr = replyToString(lenBuf);

					int len;
					try
					{
						len = Convert.ToInt32(lenStr, 16);
					}
                    catch (SystemException)
					{
						Log.w("ddms", "Expected digits, got '" + lenStr + "': " + lenBuf[0] + " " + lenBuf[1] + " " + lenBuf[2] + " " + lenBuf[3]);
						Log.w("ddms", "reply was " + replyToString(reply));
						break;
					}

					var msg = new byte[len];
					read(chan, msg);

					resp.message = replyToString(msg);
					Log.v("ddms", "Got reply '" + replyToString(reply) + "', diag='" + resp.message + "'");

					break;
				}
			}
			catch (Exception)
			{
				// ignore those, since it's just reading the diagnose string, the response will
				// contain okay==false anyway.
			}

			return resp;
		}
Beispiel #7
0
		/// <summary>
		/// Create an object for a new client connection.
		/// </summary>
		/// <param name="device"> the device this client belongs to </param>
		/// <param name="chan"> the connected <seealso cref="SocketChannel"/>. </param>
		/// <param name="pid"> the client pid. </param>
		internal Client(Device device, SocketChannel chan, int pid)
		{
			mDevice = device;
			mChan = chan;

			mReadBuffer = ByteBuffer.allocate(INITIAL_BUF_SIZE);
			mWriteBuffer = ByteBuffer.allocate(WRITE_BUF_SIZE);

			mOutstandingReqs = new Dictionary<int?, ChunkHandler>();

			mConnState = ST_INIT;

			mClientData = new ClientData(pid);

			mThreadUpdateEnabled = DdmPreferences.initialThreadUpdate;
			mHeapUpdateEnabled = DdmPreferences.initialHeapUpdate;
		}
Beispiel #8
0
		/// <summary>
		/// Accept a new connection from the specified listen channel.  This
		/// is so we can listen on a dedicated port for the "current" client,
		/// where "current" is constantly in flux.
		/// 
		/// Must be synchronized with other uses of mChannel and mPreBuffer.
		/// 
		/// Returns "null" if we're already talking to somebody.
		/// </summary>
		internal SocketChannel accept(ServerSocketChannel listenChan)
		{

		    if(listenChan != null)
		    {
		        SocketChannel newChan;

		        newChan = listenChan.accept();
		        if(mChannel != null)
		        {
		            Log.w("ddms", "debugger already talking to " + mClient + " on " + mListenPort);
		            newChan.close();
		            return null;
		        }
		        mChannel = newChan;
		        mChannel.configureBlocking(false); // required for Selector
		        mConnState = ST_AWAIT_SHAKE;
		        return mChannel;

		    }
            return null;
        }
Beispiel #9
0
        //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
        //ORIGINAL LINE: private void processIncomingJdwpData(Device device, java.nio.channels.SocketChannel monitorSocket, int length) throws java.io.IOException
        private void processIncomingJdwpData(Device device, SocketChannel monitorSocket, int length)
        {
            if (length >= 0)
            {
                // array for the current pids.
                List<int?> pidList = new List<int?>();

                // get the string data if there are any
                if (length > 0)
                {
                    var buffer = new byte[length];
                    string result = read(monitorSocket, buffer);

                    // split each line in its own list and create an array of integer pid
                    string[] pids = StringHelperClass.StringSplit(result, "\n", true); //$NON-NLS-1$

                    foreach (string pid in pids)
                    {
                        try
                        {
                            pidList.Add(Convert.ToInt32(pid));
                        }
                        catch (SystemException)
                        {
                            // looks like this pid is not really a number. Lets ignore it.
                            continue;
                        }
                    }
                }

                MonitorThread monitorThread = MonitorThread.instance;

                // Now we merge the current list with the old one.
                // this is the same mechanism as the merging of the device list.

                // For each client in the current list, we look for a matching the pid in the new list.
                // * if we find it, we do nothing, except removing the pid from its list,
                //   to mark it as "processed"
                // * if we do not find any match, we remove the client from the current list.
                // Once this is done, the new list contains pids for which we don't have clients yet,
                // so we create clients for them, add them to the list, and start monitoring them.

                IList<Client> clients = device.clientList;

                bool changed = false;

                // because MonitorThread#dropClient acquires first the monitorThread lock and then the
                // Device client list lock (when removing the Client from the list), we have to make
                // sure we acquire the locks in the same order, since another thread (MonitorThread),
                // could call dropClient itself.
                lock (monitorThread)
                {
                    lock (clients)
                    {
                        for (int c = 0; c < clients.Count; )
                        {
                            Client client = clients[c];
                            int pid = client.clientData.pid;

                            // look for a matching pid
                            int? match = null;
                            foreach (int? matchingPid in pidList)
                            {
                                if (pid == (int)matchingPid)
                                {
                                    match = matchingPid;
                                    break;
                                }
                            }

                            if (match != null)
                            {
                                pidList.Remove(match);
                                c++; // move on to the next client.
                            }
                            else
                            {
                                // we need to drop the client. the client will remove itself from the
                                // list of its device which is 'clients', so there's no need to
                                // increment c.
                                // We ask the monitor thread to not send notification, as we'll do
                                // it once at the end.
                                monitorThread.dropClient(client, false); // notify
                                changed = true;
                            }
                        }
                    }
                }

                // at this point whatever pid is left in the list needs to be converted into Clients.
                foreach (int newPid in pidList)
                {
                    openClient(device, newPid, nextDebuggerPort, monitorThread);
                    changed = true;
                }

                if (changed)
                {
                    mServer.deviceChanged(device, DeviceConstants.CHANGE_CLIENT_LIST);
                }
            }
        }
Beispiel #10
0
        /// <summary>
        /// Creates a client and register it to the monitor thread </summary>
        /// <param name="device"> </param>
        /// <param name="pid"> </param>
        /// <param name="socket"> </param>
        /// <param name="debuggerPort"> the debugger port. </param>
        /// <param name="monitorThread"> the <seealso cref="MonitorThread"/> object. </param>
        private void createClient(Device device, int pid, SocketChannel socket, int debuggerPort, MonitorThread monitorThread)
        {

            /*
             * Successfully connected to something. Create a Client object, add
             * it to the list, and initiate the JDWP handshake.
             */

            Client client = new Client(device, socket, pid);

            if (client.sendHandshake())
            {
                try
                {
                    if (AndroidDebugBridge.clientSupport)
                    {
                        client.listenForDebugger(debuggerPort);
                    }
                }
                catch (IOException)
                {
                    client.clientData.debuggerConnectionStatus = ClientData.DebuggerStatus.ERROR;
                    Log.e("ddms", "Can't bind to local " + debuggerPort + " for debugger");
                    // oh well
                }

                client.requestAllocationStatus();
            }
            else
            {
                Log.e("ddms", "Handshake with " + client + " failed!");
                /*
                 * The handshake send failed. We could remove it now, but if the
                 * failure is "permanent" we'll just keep banging on it and
                 * getting the same result. Keep it in the list with its "error"
                 * state so we don't try to reopen it.
                 */
            }

            if (client.valid)
            {
                device.addClient(client);
                monitorThread.addClient(client);
            }
            else
            {
                client = null;
            }
        }
Beispiel #11
0
        //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
        //ORIGINAL LINE: private boolean sendDeviceMonitoringRequest(java.nio.channels.SocketChannel socket, Device device) throws TimeoutException, AdbCommandRejectedException, java.io.IOException
        private bool sendDeviceMonitoringRequest(SocketChannel socket, Device device)
        {

            try
            {
                AdbHelper.setDevice(socket, device);

                var request = AdbHelper.formAdbRequest("track-jdwp"); //$NON-NLS-1$

                AdbHelper.write(socket, request);

                AdbHelper.AdbResponse resp = AdbHelper.readAdbResponse(socket, false); // readDiagString

                if (resp.okay == false)
                {
                    // request was refused by adb!
                    Log.e("DeviceMonitor", "adb refused request: " + resp.message);
                }

                return resp.okay;
            }
            catch (TimeoutException e)
            {
                Log.e("DeviceMonitor", "Sending jdwp tracking request timed out!");
                throw e;
            }
            catch (IOException e)
            {
                Log.e("DeviceMonitor", "Sending jdwp tracking request failed!");
                throw e;
            }
        }
Beispiel #12
0
        private void handleExpectioninMonitorLoop(Exception e)
        {
            if (mQuit == false)
            {
                if (e is TimeoutException)
                {
                    Log.e("DeviceMonitor", "Adb connection Error: timeout");
                }
                else
                {
                    Log.e("DeviceMonitor", "Adb connection Error:" + e.Message);
                }
                mMonitoring = false;
                if (mMainAdbConnection != null)
                {
                    try
                    {
                        mMainAdbConnection.close();
                    }
                    catch (IOException)
                    {
                        // we can safely ignore that one.
                    }
                    mMainAdbConnection = null;

                    // remove all devices from list
                    // because we are going to call mServer.deviceDisconnected which will acquire this
                    // lock we lock it first, so that the AndroidDebugBridge lock is always locked
                    // first.
                    lock (AndroidDebugBridge.@lock)
                    {
                        lock (mDevices)
                        {
                            for (int n = mDevices.Count - 1; n >= 0; n--)
                            {
                                Device device = mDevices[0];
                                removeDevice(device);
                                mServer.deviceDisconnected(device);
                            }
                        }
                    }
                }
            }
        }
Beispiel #13
0
        /// <summary>
        /// Monitors the devices. This connects to the Debug Bridge
        /// </summary>
        private void deviceMonitorLoop()
        {
            do
            {
                try
                {
                    if (mMainAdbConnection == null)
                    {
                        Log.d("DeviceMonitor", "Opening adb connection");
                        mMainAdbConnection = openAdbConnection();
                        if (mMainAdbConnection == null)
                        {
                            mConnectionAttempt++;
                            Log.e("DeviceMonitor", "Connection attempts: " + mConnectionAttempt);
                            if (mConnectionAttempt > 10)
                            {
                                if (mServer.startAdb() == false)
                                {
                                    mRestartAttemptCount++;
                                    Log.e("DeviceMonitor", "adb restart attempts: " + mRestartAttemptCount);
                                }
                                else
                                {
                                    mRestartAttemptCount = 0;
                                }
                            }
                            waitABit();
                        }
                        else
                        {
                            Log.d("DeviceMonitor", "Connected to adb for device monitoring");
                            mConnectionAttempt = 0;
                        }
                    }

                    if (mMainAdbConnection != null && mMonitoring == false)
                    {
                        mMonitoring = sendDeviceListMonitoringRequest();
                    }

                    if (mMonitoring)
                    {
                        // read the length of the incoming message
                        int length = readLength(mMainAdbConnection, mLengthBuffer);

                        if (length >= 0)
                        {
                            // read the incoming message
                            processIncomingDeviceData(length);

                            // flag the fact that we have build the list at least once.
                            mInitialDeviceListDone = true;
                        }
                    }
                }
                /*catch (AsynchronousCloseException ace)
                {
                    // this happens because of a call to Quit. We do nothing, and the loop will break.
                }*/
                catch (TimeoutException ioe)
                {
                    handleExpectioninMonitorLoop(ioe);
                }
                catch (IOException ioe)
                {
                    handleExpectioninMonitorLoop(ioe);
                }
            } while (mQuit == false);
        }
Beispiel #14
0
        /// <summary>
        /// Opens the sync connection. This must be called before any calls to push[File] / pull[File]. </summary>
        /// <returns> true if the connection opened, false if adb refuse the connection. This can happen
        /// if the <seealso cref="Device"/> is invalid. </returns>
        /// <exception cref="TimeoutException"> in case of timeout on the connection. </exception>
        /// <exception cref="AdbCommandRejectedException"> if adb rejects the command </exception>
        /// <exception cref="IOException"> If the connection to adb failed. </exception>
        //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
        //ORIGINAL LINE: boolean openSync() throws TimeoutException, AdbCommandRejectedException, java.io.IOException
        internal bool openSync()
        {
            try
            {
                mChannel = SocketChannel.open(mAddress);
                mChannel.configureBlocking(false);

                // target a specific device
                AdbHelper.setDevice(mChannel, mDevice);

                var request = AdbHelper.formAdbRequest("sync:"); //$NON-NLS-1$
                AdbHelper.write(mChannel, request, -1, DdmPreferences.timeOut);

                AdbHelper.AdbResponse resp = AdbHelper.readAdbResponse(mChannel, false); // readDiagString

                if (resp.okay == false)
                {
                    Log.w("ddms", "Got unhappy response from ADB sync req: " + resp.message);
                    mChannel.close();
                    mChannel = null;
                    return false;
                }
            }
            catch (TimeoutException e)
            {
                if (mChannel != null)
                {
                    try
                    {
                        mChannel.close();
                    }
                    catch (IOException)
                    {
                        // we want to throw the original exception, so we ignore this one.
                    }
                    mChannel = null;
                }

                throw e;
            }
            catch (IOException e)
            {
                if (mChannel != null)
                {
                    try
                    {
                        mChannel.close();
                    }
                    catch (IOException)
                    {
                        // we want to throw the original exception, so we ignore this one.
                    }
                    mChannel = null;
                }

                throw e;
            }

            return true;
        }
Beispiel #15
0
		/// <summary>
		/// Close the client socket channel.  If there is a debugger associated
		/// with us, close that too.
		/// 
		/// Closing a channel automatically unregisters it from the selector.
		/// However, we have to iterate through the selector loop before it
		/// actually lets them go and allows the file descriptors to close.
		/// The caller is expected to manage that. </summary>
		/// <param name="notify"> Whether or not to notify the listeners of a change. </param>
		internal virtual void close(bool notify)
		{
			Log.d("ddms", "Closing " + this.ToString());

			mOutstandingReqs.Clear();

			try
			{
				if (mChan != null)
				{
					mChan.close();
					mChan = null;
				}

				if (mDebugger != null)
				{
					mDebugger.close();
					mDebugger = null;
				}
			}
			catch (IOException)
			{
				Log.w("ddms", "failed to close " + this);
				// swallow it -- not much else to do
			}

			mDevice.removeClient(this, notify);
		}
Beispiel #16
0
		/// <summary>
		/// Starts the connection of the console. </summary>
		/// <returns> true if success. </returns>
		private bool start()
		{

			DnsEndPoint socketAddr;
			try
			{
				socketAddr = new DnsEndPoint(HOST, mPort);
			}
			catch (ArgumentException)
			{
				return false;
			}

			try
			{
				mSocketChannel = SocketChannel.open(socketAddr);
			}
			catch (IOException)
			{
				return false;
			}

			// read some stuff from it
			readLines();

			return true;
		}
Beispiel #17
0
        /// <summary>
        /// Write our packet to "chan".  Consumes the packet as part of the
        /// write.
        /// 
        /// The JDWP packet starts at offset 0 and ends at mBuffer.position().
        /// </summary>
        //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
        //ORIGINAL LINE: void writeAndConsume(java.nio.channels.SocketChannel chan) throws java.io.IOException
        internal void writeAndConsume(SocketChannel chan)
        {
            int oldLimit;

            //Log.i("ddms", "writeAndConsume: pos=" + mBuffer.position()
            //    + ", limit=" + mBuffer.limit());

            Debug.Assert(mLength > 0);

            mBuffer.flip(); // limit<-posn, posn<-0
            oldLimit = mBuffer.limit;
            mBuffer.limit = (mLength);
            while (mBuffer.position != mBuffer.limit)
            {
                chan.write(mBuffer);
            }
            // position should now be at end of packet
            Debug.Assert(mBuffer.position == mLength);

            mBuffer.limit= (oldLimit);
            mBuffer.compact(); // shift posn...limit, posn<-pending data

            //Log.i("ddms", "               : pos=" + mBuffer.position()
            //    + ", limit=" + mBuffer.limit());
        }
Beispiel #18
0
	    /// <summary>
		/// Close the data connection only.
		/// </summary>
		/*lock*/
	    internal void closeData()
		{
			try
			{
				if (mChannel != null)
				{
					mChannel.close();
					mChannel = null;
					mConnState = ST_NOT_CONNECTED;

					ClientData cd = mClient.clientData;
					cd.debuggerConnectionStatus = ClientData.DebuggerStatus.DEFAULT;
					mClient.update(Client.CHANGE_DEBUGGER_STATUS);
				}
			}
			catch (IOException)
			{
				Log.w("ddms", "Failed to close data " + this);
			}
		}
Beispiel #19
0
        /// <summary>
        /// Reads the length of the next message from a socket. </summary>
        /// <param name="socket"> The <seealso cref="SocketChannel"/> to read from. </param>
        /// <returns> the length, or 0 (zero) if no data is available from the socket. </returns>
        /// <exception cref="IOException"> if the connection failed. </exception>
        //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
        //ORIGINAL LINE: private int readLength(java.nio.channels.SocketChannel socket, byte[] buffer) throws java.io.IOException
        private int readLength(SocketChannel socket, byte[] buffer)
        {
            string msg = read(socket, buffer);

            if (msg != null)
            {
                try
                {
                    return Convert.ToInt32(msg, 16);
                }
                catch (SystemException)
                {
                    // we'll throw an exception below.
                }
            }

            // we receive something we can't read. It's better to reset the connection at this point.
            throw new IOException("Unable to read length");
        }