diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/CollectTraceAction.java')
-rw-r--r-- | eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/CollectTraceAction.java | 428 |
1 files changed, 0 insertions, 428 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/CollectTraceAction.java b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/CollectTraceAction.java deleted file mode 100644 index c13ab461b..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/CollectTraceAction.java +++ /dev/null @@ -1,428 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.gltrace; - -import com.android.ddmlib.AdbCommandRejectedException; -import com.android.ddmlib.AndroidDebugBridge; -import com.android.ddmlib.Client; -import com.android.ddmlib.IDevice; -import com.android.ddmlib.IDevice.DeviceUnixSocketNamespace; -import com.android.ddmlib.IShellOutputReceiver; -import com.android.ddmlib.ShellCommandUnresponsiveException; -import com.android.ddmlib.TimeoutException; -import com.android.ide.eclipse.gltrace.editors.GLFunctionTraceViewer; -import com.google.common.io.Closeables; -import com.google.common.util.concurrent.SimpleTimeLimiter; - -import org.eclipse.core.filesystem.EFS; -import org.eclipse.core.filesystem.IFileStore; -import org.eclipse.core.runtime.Path; -import org.eclipse.jface.action.IAction; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.window.Window; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.IEditorReference; -import org.eclipse.ui.IURIEditorInput; -import org.eclipse.ui.IWorkbench; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.IWorkbenchWindow; -import org.eclipse.ui.IWorkbenchWindowActionDelegate; -import org.eclipse.ui.PartInitException; -import org.eclipse.ui.PlatformUI; -import org.eclipse.ui.WorkbenchException; -import org.eclipse.ui.ide.IDE; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.net.Socket; -import java.util.concurrent.Callable; -import java.util.concurrent.Semaphore; -import java.util.concurrent.TimeUnit; - -public class CollectTraceAction implements IWorkbenchWindowActionDelegate { - /** Abstract Unix Domain Socket Name used by the gltrace device code. */ - private static final String GLTRACE_UDS = "gltrace"; //$NON-NLS-1$ - - /** Local port that is forwarded to the device's {@link #GLTRACE_UDS} socket. */ - private static final int LOCAL_FORWARDED_PORT = 6039; - - /** Activity name to use for a system activity that has already been launched. */ - private static final String SYSTEM_APP = "system"; //$NON-NLS-1$ - - /** Time to wait for the application to launch (seconds) */ - private static final int LAUNCH_TIMEOUT = 15; - - /** Time to wait for the application to die (seconds) */ - private static final int KILL_TIMEOUT = 5; - - private static final int MIN_API_LEVEL = 16; - - @Override - public void run(IAction action) { - connectToDevice(); - } - - @Override - public void selectionChanged(IAction action, ISelection selection) { - } - - @Override - public void dispose() { - } - - @Override - public void init(IWorkbenchWindow window) { - } - - private void connectToDevice() { - Shell shell = Display.getDefault().getActiveShell(); - GLTraceOptionsDialog dlg = new GLTraceOptionsDialog(shell); - if (dlg.open() != Window.OK) { - return; - } - - TraceOptions traceOptions = dlg.getTraceOptions(); - - IDevice device = getDevice(traceOptions.device); - String apiLevelString = device.getProperty(IDevice.PROP_BUILD_API_LEVEL); - int apiLevel; - try { - apiLevel = Integer.parseInt(apiLevelString); - } catch (NumberFormatException e) { - apiLevel = MIN_API_LEVEL; - } - if (apiLevel < MIN_API_LEVEL) { - MessageDialog.openError(shell, "GL Trace", - String.format("OpenGL Tracing is only supported on devices at API Level %1$d." - + "The selected device '%2$s' provides API level %3$s.", - MIN_API_LEVEL, traceOptions.device, apiLevelString)); - return; - } - - try { - setupForwarding(device, LOCAL_FORWARDED_PORT); - } catch (Exception e) { - MessageDialog.openError(shell, "Setup GL Trace", - "Error while setting up port forwarding: " + e.getMessage()); - return; - } - - try { - if (!SYSTEM_APP.equals(traceOptions.appToTrace)) { - startActivity(device, traceOptions.appToTrace, traceOptions.activityToTrace, - traceOptions.isActivityNameFullyQualified); - } - } catch (Exception e) { - MessageDialog.openError(shell, "Setup GL Trace", - "Error while launching application: " + e.getMessage()); - return; - } - - // if everything went well, the app should now be waiting for the gl debugger - // to connect - startTracing(shell, traceOptions, LOCAL_FORWARDED_PORT); - - // once tracing is complete, remove port forwarding - disablePortForwarding(device, LOCAL_FORWARDED_PORT); - - // and finally open the editor to view the file - openInEditor(shell, traceOptions.traceDestination); - } - - public static void openInEditor(Shell shell, String traceFilePath) { - final IFileStore fileStore = EFS.getLocalFileSystem().getStore(new Path(traceFilePath)); - if (!fileStore.fetchInfo().exists()) { - return; - } - - final IWorkbench workbench = PlatformUI.getWorkbench(); - IWorkbenchWindow window = workbench.getActiveWorkbenchWindow(); - if (window == null) { - return; - } - - IWorkbenchPage page = window.getActivePage(); - if (page == null) { - return; - } - - try { - workbench.showPerspective("com.android.ide.eclipse.gltrace.perspective", window); - } catch (WorkbenchException e) { - } - - // if there is a editor already open, then refresh its model - GLFunctionTraceViewer viewer = getOpenTraceViewer(page, traceFilePath); - if (viewer != null) { - viewer.setInput(shell, traceFilePath); - } - - // open the editor (if not open), or bring it to foreground if it is already open - try { - IDE.openEditorOnFileStore(page, fileStore); - } catch (PartInitException e) { - GlTracePlugin.getDefault().logMessage( - "Unexpected error while opening gltrace file in editor: " + e); - return; - } - } - - /** - * Returns the editor part that has the provided file path open. - * @param page page containing editors - * @param traceFilePath file that should be open in an editor - * @return if given trace file is already open, then a reference to that editor part, - * null otherwise - */ - private static GLFunctionTraceViewer getOpenTraceViewer(IWorkbenchPage page, - String traceFilePath) { - IEditorReference[] editorRefs = page.getEditorReferences(); - for (IEditorReference ref : editorRefs) { - String id = ref.getId(); - if (!GLFunctionTraceViewer.ID.equals(id)) { - continue; - } - - IEditorInput input = null; - try { - input = ref.getEditorInput(); - } catch (PartInitException e) { - continue; - } - - if (!(input instanceof IURIEditorInput)) { - continue; - } - - if (traceFilePath.equals(((IURIEditorInput) input).getURI().getPath())) { - return (GLFunctionTraceViewer) ref.getEditor(true); - } - } - - return null; - } - - @SuppressWarnings("resource") // Closeables.closeQuietly - public static void startTracing(Shell shell, TraceOptions traceOptions, int port) { - Socket socket = new Socket(); - DataInputStream traceDataStream = null; - DataOutputStream traceCommandsStream = null; - try { - socket.connect(new java.net.InetSocketAddress("127.0.0.1", port)); //$NON-NLS-1$ - socket.setTcpNoDelay(true); - traceDataStream = new DataInputStream(socket.getInputStream()); - traceCommandsStream = new DataOutputStream(socket.getOutputStream()); - } catch (IOException e) { - MessageDialog.openError(shell, - "OpenGL Trace", - "Unable to connect to remote GL Trace Server: " + e.getMessage()); - return; - } - - // create channel to send trace commands to device - TraceCommandWriter traceCommandWriter = new TraceCommandWriter(traceCommandsStream); - try { - traceCommandWriter.setTraceOptions(traceOptions.collectFbOnEglSwap, - traceOptions.collectFbOnGlDraw, - traceOptions.collectTextureData); - } catch (IOException e) { - MessageDialog.openError(shell, - "OpenGL Trace", - "Unexpected error while setting trace options: " + e.getMessage()); - closeSocket(socket); - return; - } - - FileOutputStream fos = null; - try { - fos = new FileOutputStream(traceOptions.traceDestination, false); - } catch (FileNotFoundException e) { - // input path is valid, so this cannot occur - } - - // create trace writer that writes to a trace file - TraceFileWriter traceFileWriter = new TraceFileWriter(fos, traceDataStream); - traceFileWriter.start(); - - GLTraceCollectorDialog dlg = new GLTraceCollectorDialog(shell, - traceFileWriter, - traceCommandWriter, - traceOptions); - dlg.open(); - - traceFileWriter.stopTracing(); - traceCommandWriter.close(); - closeSocket(socket); - } - - private static void closeSocket(Socket socket) { - try { - socket.close(); - } catch (IOException e) { - // ignore error while closing socket - } - } - - private void startActivity(IDevice device, String appPackage, String activity, - boolean isActivityNameFullyQualified) - throws TimeoutException, AdbCommandRejectedException, - ShellCommandUnresponsiveException, IOException, InterruptedException { - killApp(device, appPackage); // kill app if it is already running - waitUntilAppKilled(device, appPackage, KILL_TIMEOUT); - - StringBuilder activityPath = new StringBuilder(appPackage); - if (!activity.isEmpty()) { - activityPath.append('/'); - if (!isActivityNameFullyQualified) { - activityPath.append('.'); - } - activityPath.append(activity); - } - String startAppCmd = String.format( - "am start --opengl-trace %s -a android.intent.action.MAIN -c android.intent.category.LAUNCHER", //$NON-NLS-1$ - activityPath.toString()); - - Semaphore launchCompletionSempahore = new Semaphore(0); - StartActivityOutputReceiver receiver = new StartActivityOutputReceiver( - launchCompletionSempahore); - device.executeShellCommand(startAppCmd, receiver); - - // wait until shell finishes launch command - launchCompletionSempahore.acquire(); - - // throw exception if there was an error during launch - String output = receiver.getOutput(); - if (output.contains("Error")) { //$NON-NLS-1$ - throw new RuntimeException(output); - } - - // wait until the app itself has been launched - waitUntilAppLaunched(device, appPackage, LAUNCH_TIMEOUT); - } - - private void killApp(IDevice device, String appName) { - Client client = device.getClient(appName); - if (client != null) { - client.kill(); - } - } - - private void waitUntilAppLaunched(final IDevice device, final String appName, int timeout) { - Callable<Boolean> c = new Callable<Boolean>() { - @Override - public Boolean call() throws Exception { - Client client; - do { - client = device.getClient(appName); - } while (client == null); - - return Boolean.TRUE; - } - }; - try { - new SimpleTimeLimiter().callWithTimeout(c, timeout, TimeUnit.SECONDS, true); - } catch (Exception e) { - throw new RuntimeException("Timed out waiting for application to launch."); - } - - // once the app has launched, wait an additional couple of seconds - // for it to start up - try { - Thread.sleep(2000); - } catch (InterruptedException e) { - // ignore - } - } - - private void waitUntilAppKilled(final IDevice device, final String appName, int timeout) { - Callable<Boolean> c = new Callable<Boolean>() { - @Override - public Boolean call() throws Exception { - Client client; - while ((client = device.getClient(appName)) != null) { - client.kill(); - } - return Boolean.TRUE; - } - }; - try { - new SimpleTimeLimiter().callWithTimeout(c, timeout, TimeUnit.SECONDS, true); - } catch (Exception e) { - throw new RuntimeException("Timed out waiting for running application to die."); - } - } - - public static void setupForwarding(IDevice device, int i) - throws TimeoutException, AdbCommandRejectedException, IOException { - device.createForward(i, GLTRACE_UDS, DeviceUnixSocketNamespace.ABSTRACT); - } - - public static void disablePortForwarding(IDevice device, int port) { - try { - device.removeForward(port, GLTRACE_UDS, DeviceUnixSocketNamespace.ABSTRACT); - } catch (Exception e) { - // ignore exceptions; - } - } - - private IDevice getDevice(String deviceName) { - IDevice[] devices = AndroidDebugBridge.getBridge().getDevices(); - - for (IDevice device : devices) { - if (device.getName().equals(deviceName)) { - return device; - } - } - - return null; - } - - private static class StartActivityOutputReceiver implements IShellOutputReceiver { - private Semaphore mSemaphore; - private StringBuffer sb = new StringBuffer(300); - - public StartActivityOutputReceiver(Semaphore s) { - mSemaphore = s; - } - - @Override - public void addOutput(byte[] data, int offset, int length) { - String d = new String(data, offset, length); - sb.append(d); - } - - @Override - public void flush() { - mSemaphore.release(); - } - - @Override - public boolean isCancelled() { - return false; - } - - public String getOutput() { - return sb.toString(); - } - } -} |