diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.ndk/src/com/android/ide/eclipse/ndk/internal/launch/GdbServerTask.java')
-rw-r--r-- | eclipse/plugins/com.android.ide.eclipse.ndk/src/com/android/ide/eclipse/ndk/internal/launch/GdbServerTask.java | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.ndk/src/com/android/ide/eclipse/ndk/internal/launch/GdbServerTask.java b/eclipse/plugins/com.android.ide.eclipse.ndk/src/com/android/ide/eclipse/ndk/internal/launch/GdbServerTask.java new file mode 100644 index 000000000..23486ee6f --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.ndk/src/com/android/ide/eclipse/ndk/internal/launch/GdbServerTask.java @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Eclipse Public License, Version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.eclipse.org/org/documents/epl-v10.php + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.ide.eclipse.ndk.internal.launch; + +import com.android.ddmlib.IDevice; +import com.android.ddmlib.IShellOutputReceiver; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * The {@link GdbServerTask} launches gdbserver on the given device and attaches it to + * provided pid. + */ +public class GdbServerTask implements Runnable { + private IDevice mDevice; + private String mRunAs; + private String mSocket; + private int mPid; + private CountDownLatch mAttachLatch; + + private GdbServerOutputReceiver mOutputReceiver; + private Exception mLaunchException; + + private AtomicBoolean mCancelled = new AtomicBoolean(false); + private AtomicBoolean mHasCompleted = new AtomicBoolean(false); + + /** + * Construct a gdbserver task. + * @param device device to run gdbserver on + * @param runAsPackage name of the package in which gdbserver resides + * @param socketName name of the local socket on which the server will listen + * @param pid pid of task to attach to + * @param attachLatch latch to notify when gdbserver gets attached to the task + */ + public GdbServerTask(IDevice device, String runAsPackage, String socketName, int pid, + CountDownLatch attachLatch) { + mDevice = device; + mRunAs = runAsPackage; + mSocket = socketName; + mPid = pid; + mAttachLatch = attachLatch; + + mOutputReceiver = new GdbServerOutputReceiver(); + } + + /** + * Runs gdbserver on the device and connects to the given task. If gdbserver manages to + * successfully attach itself to the process, then it counts down on its attach latch. + */ + @Override + public void run() { + // Launch gdbserver on the device. + String command = String.format("run-as %s lib/gdbserver +%s --attach %d", + mRunAs, mSocket, mPid); + try { + mDevice.executeShellCommand(command, mOutputReceiver, 0); + } catch (Exception e) { + mLaunchException = e; + } + } + + /** Returns any exceptions that might have occurred while launching gdbserver. */ + public Exception getLaunchException() { + return mLaunchException; + } + + /** Cancel gdbserver if it is running. */ + public void setCancelled() { + mCancelled.set(true); + } + + public String getShellOutput() { + return mOutputReceiver.getOutput(); + } + + private class GdbServerOutputReceiver implements IShellOutputReceiver { + private StringBuffer mOutput = new StringBuffer(100); + + @Override + public synchronized void addOutput(byte[] data, int offset, int length) { + mOutput.append(new String(data, offset, length)); + + // notify other threads that gdbserver has attached to the task + if (mOutput.toString().contains("Attached")) { + mAttachLatch.countDown(); + } + } + + @Override + public void flush() { + mHasCompleted.set(true); + } + + @Override + public boolean isCancelled() { + return mCancelled.get(); + } + + public synchronized String getOutput() { + return mOutput.toString(); + } + } +} |