diff options
Diffstat (limited to 'hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device')
8 files changed, 0 insertions, 1727 deletions
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/AbstractHvDevice.java b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/AbstractHvDevice.java deleted file mode 100644 index e330168..0000000 --- a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/AbstractHvDevice.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2013 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.hierarchyviewerlib.device; - -import com.android.ddmlib.AdbCommandRejectedException; -import com.android.ddmlib.IDevice; -import com.android.ddmlib.Log; -import com.android.ddmlib.RawImage; -import com.android.ddmlib.TimeoutException; - -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.ImageData; -import org.eclipse.swt.graphics.PaletteData; -import org.eclipse.swt.widgets.Display; - -import java.io.IOException; -import java.util.concurrent.atomic.AtomicReference; - -public abstract class AbstractHvDevice implements IHvDevice { - private static final String TAG = "HierarchyViewer"; - - @Override - public Image getScreenshotImage() { - IDevice device = getDevice(); - final AtomicReference<Image> imageRef = new AtomicReference<Image>(); - - try { - final RawImage screenshot = device.getScreenshot(); - if (screenshot == null) { - return null; - } - Display.getDefault().syncExec(new Runnable() { - @Override - public void run() { - ImageData imageData = - new ImageData(screenshot.width, screenshot.height, screenshot.bpp, - new PaletteData(screenshot.getRedMask(), screenshot - .getGreenMask(), screenshot.getBlueMask()), 1, - screenshot.data); - imageRef.set(new Image(Display.getDefault(), imageData)); - } - }); - return imageRef.get(); - } catch (IOException e) { - Log.e(TAG, "Unable to load screenshot from device " + device.getName()); - } catch (TimeoutException e) { - Log.e(TAG, "Timeout loading screenshot from device " + device.getName()); - } catch (AdbCommandRejectedException e) { - Log.e(TAG, "Adb rejected command to load screenshot from device " + device.getName()); - } - return null; - } -} diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/DdmViewDebugDevice.java b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/DdmViewDebugDevice.java deleted file mode 100644 index 0172995..0000000 --- a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/DdmViewDebugDevice.java +++ /dev/null @@ -1,417 +0,0 @@ -/* - * Copyright (C) 2013 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.hierarchyviewerlib.device; - -import com.android.ddmlib.AndroidDebugBridge; -import com.android.ddmlib.AndroidDebugBridge.IDeviceChangeListener; -import com.android.ddmlib.Client; -import com.android.ddmlib.ClientData; -import com.android.ddmlib.HandleViewDebug; -import com.android.ddmlib.HandleViewDebug.ViewDumpHandler; -import com.android.ddmlib.IDevice; -import com.android.ddmlib.Log; -import com.android.hierarchyviewerlib.device.WindowUpdater.IWindowChangeListener; -import com.android.hierarchyviewerlib.models.ViewNode; -import com.android.hierarchyviewerlib.models.Window; -import com.android.hierarchyviewerlib.ui.util.PsdFile; - -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Display; - -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.DataInputStream; -import java.io.IOException; -import java.io.StringReader; -import java.nio.ByteBuffer; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; - -public class DdmViewDebugDevice extends AbstractHvDevice implements IDeviceChangeListener { - private static final String TAG = "DdmViewDebugDevice"; - - private final IDevice mDevice; - private Map<Client, List<String>> mViewRootsPerClient = new HashMap<Client, List<String>>(40); - - public DdmViewDebugDevice(IDevice device) { - mDevice = device; - } - - @Override - public boolean initializeViewDebug() { - AndroidDebugBridge.addDeviceChangeListener(this); - return reloadWindows(); - } - - private static class ListViewRootsHandler extends ViewDumpHandler { - private List<String> mViewRoots = Collections.synchronizedList(new ArrayList<String>(10)); - - public ListViewRootsHandler() { - super(HandleViewDebug.CHUNK_VULW); - } - - @Override - protected void handleViewDebugResult(ByteBuffer data) { - int nWindows = data.getInt(); - - for (int i = 0; i < nWindows; i++) { - int len = data.getInt(); - mViewRoots.add(getString(data, len)); - } - } - - public List<String> getViewRoots(long timeout, TimeUnit unit) { - waitForResult(timeout, unit); - return mViewRoots; - } - } - - private static class CaptureByteArrayHandler extends ViewDumpHandler { - public CaptureByteArrayHandler(int type) { - super(type); - } - - private AtomicReference<byte[]> mData = new AtomicReference<byte[]>(); - - @Override - protected void handleViewDebugResult(ByteBuffer data) { - byte[] b = new byte[data.remaining()]; - data.get(b); - mData.set(b); - - } - - public byte[] getData(long timeout, TimeUnit unit) { - waitForResult(timeout, unit); - return mData.get(); - } - } - - private static class CaptureLayersHandler extends ViewDumpHandler { - private AtomicReference<PsdFile> mPsd = new AtomicReference<PsdFile>(); - - public CaptureLayersHandler() { - super(HandleViewDebug.CHUNK_VURT); - } - - @Override - protected void handleViewDebugResult(ByteBuffer data) { - byte[] b = new byte[data.remaining()]; - data.get(b); - DataInputStream dis = new DataInputStream(new ByteArrayInputStream(b)); - try { - mPsd.set(DeviceBridge.parsePsd(dis)); - } catch (IOException e) { - Log.e(TAG, e); - } - } - - public PsdFile getPsdFile(long timeout, TimeUnit unit) { - waitForResult(timeout, unit); - return mPsd.get(); - } - } - - @Override - public boolean reloadWindows() { - mViewRootsPerClient = new HashMap<Client, List<String>>(40); - - for (Client c : mDevice.getClients()) { - ClientData cd = c.getClientData(); - if (cd != null && cd.hasFeature(ClientData.FEATURE_VIEW_HIERARCHY)) { - ListViewRootsHandler handler = new ListViewRootsHandler(); - - try { - HandleViewDebug.listViewRoots(c, handler); - } catch (IOException e) { - Log.i(TAG, "No connection to client: " + cd.getClientDescription()); - continue; - } - - List<String> viewRoots = new ArrayList<String>( - handler.getViewRoots(200, TimeUnit.MILLISECONDS)); - mViewRootsPerClient.put(c, viewRoots); - } - } - - return true; - } - - @Override - public void terminateViewDebug() { - // nothing to terminate - } - - @Override - public boolean isViewDebugEnabled() { - return true; - } - - @Override - public boolean supportsDisplayListDump() { - return true; - } - - @Override - public Window[] getWindows() { - List<Window> windows = new ArrayList<Window>(10); - - for (Client c: mViewRootsPerClient.keySet()) { - for (String viewRoot: mViewRootsPerClient.get(c)) { - windows.add(new Window(this, viewRoot, c)); - } - } - - return windows.toArray(new Window[windows.size()]); - } - - @Override - public int getFocusedWindow() { - // TODO: add support for identifying view in focus - return -1; - } - - @Override - public IDevice getDevice() { - return mDevice; - } - - @Override - public ViewNode loadWindowData(Window window) { - Client c = window.getClient(); - if (c == null) { - return null; - } - - String viewRoot = window.getTitle(); - CaptureByteArrayHandler handler = new CaptureByteArrayHandler(HandleViewDebug.CHUNK_VURT); - try { - HandleViewDebug.dumpViewHierarchy(c, viewRoot, - false /* skipChildren */, - true /* includeProperties */, - handler); - } catch (IOException e) { - Log.e(TAG, e); - return null; - } - - byte[] data = handler.getData(20, TimeUnit.SECONDS); - if (data == null) { - return null; - } - - String viewHierarchy = new String(data, Charset.forName("UTF-8")); - return DeviceBridge.parseViewHierarchy(new BufferedReader(new StringReader(viewHierarchy)), - window); - } - - @Override - public void loadProfileData(Window window, ViewNode viewNode) { - Client c = window.getClient(); - if (c == null) { - return; - } - - String viewRoot = window.getTitle(); - CaptureByteArrayHandler handler = new CaptureByteArrayHandler(HandleViewDebug.CHUNK_VUOP); - try { - HandleViewDebug.profileView(c, viewRoot, viewNode.toString(), handler); - } catch (IOException e) { - Log.e(TAG, e); - return; - } - - byte[] data = handler.getData(30, TimeUnit.SECONDS); - if (data == null) { - Log.e(TAG, "Timed out waiting for profile data"); - return; - } - - try { - boolean success = DeviceBridge.loadProfileDataRecursive(viewNode, - new BufferedReader(new StringReader(new String(data)))); - if (success) { - viewNode.setProfileRatings(); - } - } catch (IOException e) { - Log.e(TAG, e); - return; - } - } - - @Override - public Image loadCapture(Window window, ViewNode viewNode) { - Client c = window.getClient(); - if (c == null) { - return null; - } - - String viewRoot = window.getTitle(); - CaptureByteArrayHandler handler = new CaptureByteArrayHandler(HandleViewDebug.CHUNK_VUOP); - - try { - HandleViewDebug.captureView(c, viewRoot, viewNode.toString(), handler); - } catch (IOException e) { - Log.e(TAG, e); - return null; - } - - byte[] data = handler.getData(10, TimeUnit.SECONDS); - return (data == null) ? null : - new Image(Display.getDefault(), new ByteArrayInputStream(data)); - } - - @Override - public PsdFile captureLayers(Window window) { - Client c = window.getClient(); - if (c == null) { - return null; - } - - String viewRoot = window.getTitle(); - CaptureLayersHandler handler = new CaptureLayersHandler(); - try { - HandleViewDebug.captureLayers(c, viewRoot, handler); - } catch (IOException e) { - Log.e(TAG, e); - return null; - } - - return handler.getPsdFile(20, TimeUnit.SECONDS); - } - - @Override - public void invalidateView(ViewNode viewNode) { - Window window = viewNode.window; - Client c = window.getClient(); - if (c == null) { - return; - } - - String viewRoot = window.getTitle(); - try { - HandleViewDebug.invalidateView(c, viewRoot, viewNode.toString()); - } catch (IOException e) { - Log.e(TAG, e); - } - } - - @Override - public void requestLayout(ViewNode viewNode) { - Window window = viewNode.window; - Client c = window.getClient(); - if (c == null) { - return; - } - - String viewRoot = window.getTitle(); - try { - HandleViewDebug.requestLayout(c, viewRoot, viewNode.toString()); - } catch (IOException e) { - Log.e(TAG, e); - } - } - - @Override - public void outputDisplayList(ViewNode viewNode) { - Window window = viewNode.window; - Client c = window.getClient(); - if (c == null) { - return; - } - - String viewRoot = window.getTitle(); - try { - HandleViewDebug.dumpDisplayList(c, viewRoot, viewNode.toString()); - } catch (IOException e) { - Log.e(TAG, e); - } - } - - @Override - public void addWindowChangeListener(IWindowChangeListener l) { - // TODO: add support for listening to view root changes - } - - @Override - public void removeWindowChangeListener(IWindowChangeListener l) { - // TODO: add support for listening to view root changes - } - - @Override - public void deviceConnected(IDevice device) { - // pass - } - - @Override - public void deviceDisconnected(IDevice device) { - // pass - } - - @Override - public void deviceChanged(IDevice device, int changeMask) { - if ((changeMask & IDevice.CHANGE_CLIENT_LIST) != 0) { - reloadWindows(); - } - } - - @Override - public boolean isViewUpdateEnabled() { - return true; - } - - @Override - public void invokeViewMethod(Window window, ViewNode viewNode, String method, - List<?> args) { - Client c = window.getClient(); - if (c == null) { - return; - } - - String viewRoot = window.getTitle(); - try { - HandleViewDebug.invokeMethod(c, viewRoot, viewNode.toString(), method, args.toArray()); - } catch (IOException e) { - Log.e(TAG, e); - } - } - - @Override - public boolean setLayoutParameter(Window window, ViewNode viewNode, String property, - int value) { - Client c = window.getClient(); - if (c == null) { - return false; - } - - String viewRoot = window.getTitle(); - try { - HandleViewDebug.setLayoutParameter(c, viewRoot, viewNode.toString(), property, value); - } catch (IOException e) { - Log.e(TAG, e); - return false; - } - - return true; - } -} diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/DeviceBridge.java b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/DeviceBridge.java deleted file mode 100644 index 30fa6f6..0000000 --- a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/DeviceBridge.java +++ /dev/null @@ -1,695 +0,0 @@ -/* - * Copyright (C) 2010 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.hierarchyviewerlib.device; - -import com.android.ddmlib.AdbCommandRejectedException; -import com.android.ddmlib.AndroidDebugBridge; -import com.android.ddmlib.IDevice; -import com.android.ddmlib.Log; -import com.android.ddmlib.MultiLineReceiver; -import com.android.ddmlib.ShellCommandUnresponsiveException; -import com.android.ddmlib.TimeoutException; -import com.android.hierarchyviewerlib.models.ViewNode; -import com.android.hierarchyviewerlib.models.Window; -import com.android.hierarchyviewerlib.ui.util.PsdFile; - -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Display; - -import java.awt.Graphics2D; -import java.awt.Point; -import java.awt.image.BufferedImage; -import java.io.BufferedInputStream; -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.DataInputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.imageio.ImageIO; - -/** - * A bridge to the device. - */ -public class DeviceBridge { - - public static final String TAG = "hierarchyviewer"; - - private static final int DEFAULT_SERVER_PORT = 4939; - - // These codes must match the auto-generated codes in IWindowManager.java - // See IWindowManager.aidl as well - private static final int SERVICE_CODE_START_SERVER = 1; - - private static final int SERVICE_CODE_STOP_SERVER = 2; - - private static final int SERVICE_CODE_IS_SERVER_RUNNING = 3; - - private static AndroidDebugBridge sBridge; - - private static final HashMap<IDevice, Integer> sDevicePortMap = new HashMap<IDevice, Integer>(); - - private static final HashMap<IDevice, ViewServerInfo> sViewServerInfo = - new HashMap<IDevice, ViewServerInfo>(); - - private static int sNextLocalPort = DEFAULT_SERVER_PORT; - - public static class ViewServerInfo { - public final int protocolVersion; - - public final int serverVersion; - - ViewServerInfo(int serverVersion, int protocolVersion) { - this.protocolVersion = protocolVersion; - this.serverVersion = serverVersion; - } - } - - /** - * Init the DeviceBridge with an existing {@link AndroidDebugBridge}. - * @param bridge the bridge object to use - */ - public static void acquireBridge(AndroidDebugBridge bridge) { - sBridge = bridge; - } - - /** - * Creates an {@link AndroidDebugBridge} connected to adb at the given location. - * - * If a bridge is already running, this disconnects it and creates a new one. - * - * @param adbLocation the location to adb. - */ - public static void initDebugBridge(String adbLocation) { - if (sBridge == null) { - AndroidDebugBridge.init(true /* debugger support */); - } - if (sBridge == null || !sBridge.isConnected()) { - sBridge = AndroidDebugBridge.createBridge(adbLocation, true); - } - } - - /** Disconnects the current {@link AndroidDebugBridge}. */ - public static void terminate() { - AndroidDebugBridge.terminate(); - } - - public static IDevice[] getDevices() { - if (sBridge == null) { - return new IDevice[0]; - } - return sBridge.getDevices(); - } - - /* - * This adds a listener to the debug bridge. The listener is notified of - * connecting/disconnecting devices, devices coming online, etc. - */ - public static void startListenForDevices(AndroidDebugBridge.IDeviceChangeListener listener) { - AndroidDebugBridge.addDeviceChangeListener(listener); - } - - public static void stopListenForDevices(AndroidDebugBridge.IDeviceChangeListener listener) { - AndroidDebugBridge.removeDeviceChangeListener(listener); - } - - /** - * Sets up a just-connected device to work with the view server. - * <p/> - * This starts a port forwarding between a local port and a port on the - * device. - * - * @param device - */ - public static void setupDeviceForward(IDevice device) { - synchronized (sDevicePortMap) { - if (device.getState() == IDevice.DeviceState.ONLINE) { - int localPort = sNextLocalPort++; - try { - device.createForward(localPort, DEFAULT_SERVER_PORT); - sDevicePortMap.put(device, localPort); - } catch (TimeoutException e) { - Log.e(TAG, "Timeout setting up port forwarding for " + device); - } catch (AdbCommandRejectedException e) { - Log.e(TAG, String.format("Adb rejected forward command for device %1$s: %2$s", - device, e.getMessage())); - } catch (IOException e) { - Log.e(TAG, String.format("Failed to create forward for device %1$s: %2$s", - device, e.getMessage())); - } - } - } - } - - public static void removeDeviceForward(IDevice device) { - synchronized (sDevicePortMap) { - final Integer localPort = sDevicePortMap.get(device); - if (localPort != null) { - try { - device.removeForward(localPort, DEFAULT_SERVER_PORT); - sDevicePortMap.remove(device); - } catch (TimeoutException e) { - Log.e(TAG, "Timeout removing port forwarding for " + device); - } catch (AdbCommandRejectedException e) { - // In this case, we want to fail silently. - } catch (IOException e) { - Log.e(TAG, String.format("Failed to remove forward for device %1$s: %2$s", - device, e.getMessage())); - } - } - } - } - - public static int getDeviceLocalPort(IDevice device) { - synchronized (sDevicePortMap) { - Integer port = sDevicePortMap.get(device); - if (port != null) { - return port; - } - - Log.e(TAG, "Missing forwarded port for " + device.getSerialNumber()); - return -1; - } - - } - - public static boolean isViewServerRunning(IDevice device) { - final boolean[] result = new boolean[1]; - try { - if (device.isOnline()) { - device.executeShellCommand(buildIsServerRunningShellCommand(), - new BooleanResultReader(result)); - if (!result[0]) { - ViewServerInfo serverInfo = loadViewServerInfo(device); - if (serverInfo != null && serverInfo.protocolVersion > 2) { - result[0] = true; - } - } - } - } catch (TimeoutException e) { - Log.e(TAG, "Timeout checking status of view server on device " + device); - } catch (IOException e) { - Log.e(TAG, "Unable to check status of view server on device " + device); - } catch (AdbCommandRejectedException e) { - Log.e(TAG, "Adb rejected command to check status of view server on device " + device); - } catch (ShellCommandUnresponsiveException e) { - Log.e(TAG, "Unable to execute command to check status of view server on device " - + device); - } - return result[0]; - } - - public static boolean startViewServer(IDevice device) { - return startViewServer(device, DEFAULT_SERVER_PORT); - } - - public static boolean startViewServer(IDevice device, int port) { - final boolean[] result = new boolean[1]; - try { - if (device.isOnline()) { - device.executeShellCommand(buildStartServerShellCommand(port), - new BooleanResultReader(result)); - } - } catch (TimeoutException e) { - Log.e(TAG, "Timeout starting view server on device " + device); - } catch (IOException e) { - Log.e(TAG, "Unable to start view server on device " + device); - } catch (AdbCommandRejectedException e) { - Log.e(TAG, "Adb rejected command to start view server on device " + device); - } catch (ShellCommandUnresponsiveException e) { - Log.e(TAG, "Unable to execute command to start view server on device " + device); - } - return result[0]; - } - - public static boolean stopViewServer(IDevice device) { - final boolean[] result = new boolean[1]; - try { - if (device.isOnline()) { - device.executeShellCommand(buildStopServerShellCommand(), new BooleanResultReader( - result)); - } - } catch (TimeoutException e) { - Log.e(TAG, "Timeout stopping view server on device " + device); - } catch (IOException e) { - Log.e(TAG, "Unable to stop view server on device " + device); - } catch (AdbCommandRejectedException e) { - Log.e(TAG, "Adb rejected command to stop view server on device " + device); - } catch (ShellCommandUnresponsiveException e) { - Log.e(TAG, "Unable to execute command to stop view server on device " + device); - } - return result[0]; - } - - private static String buildStartServerShellCommand(int port) { - return String.format("service call window %d i32 %d", SERVICE_CODE_START_SERVER, port); //$NON-NLS-1$ - } - - private static String buildStopServerShellCommand() { - return String.format("service call window %d", SERVICE_CODE_STOP_SERVER); //$NON-NLS-1$ - } - - private static String buildIsServerRunningShellCommand() { - return String.format("service call window %d", SERVICE_CODE_IS_SERVER_RUNNING); //$NON-NLS-1$ - } - - private static class BooleanResultReader extends MultiLineReceiver { - private final boolean[] mResult; - - public BooleanResultReader(boolean[] result) { - mResult = result; - } - - @Override - public void processNewLines(String[] strings) { - if (strings.length > 0) { - Pattern pattern = Pattern.compile(".*?\\([0-9]{8} ([0-9]{8}).*"); //$NON-NLS-1$ - Matcher matcher = pattern.matcher(strings[0]); - if (matcher.matches()) { - if (Integer.parseInt(matcher.group(1)) == 1) { - mResult[0] = true; - } - } - } - } - - @Override - public boolean isCancelled() { - return false; - } - } - - public static ViewServerInfo loadViewServerInfo(IDevice device) { - int server = -1; - int protocol = -1; - DeviceConnection connection = null; - try { - connection = new DeviceConnection(device); - connection.sendCommand("SERVER"); //$NON-NLS-1$ - String line = connection.getInputStream().readLine(); - if (line != null) { - server = Integer.parseInt(line); - } - } catch (Exception e) { - Log.e(TAG, "Unable to get view server version from device " + device); - } finally { - if (connection != null) { - connection.close(); - } - } - connection = null; - try { - connection = new DeviceConnection(device); - connection.sendCommand("PROTOCOL"); //$NON-NLS-1$ - String line = connection.getInputStream().readLine(); - if (line != null) { - protocol = Integer.parseInt(line); - } - } catch (Exception e) { - Log.e(TAG, "Unable to get view server protocol version from device " + device); - } finally { - if (connection != null) { - connection.close(); - } - } - if (server == -1 || protocol == -1) { - return null; - } - ViewServerInfo returnValue = new ViewServerInfo(server, protocol); - synchronized (sViewServerInfo) { - sViewServerInfo.put(device, returnValue); - } - return returnValue; - } - - public static ViewServerInfo getViewServerInfo(IDevice device) { - synchronized (sViewServerInfo) { - return sViewServerInfo.get(device); - } - } - - public static void removeViewServerInfo(IDevice device) { - synchronized (sViewServerInfo) { - sViewServerInfo.remove(device); - } - } - - /* - * This loads the list of windows from the specified device. The format is: - * hashCode1 title1 hashCode2 title2 ... hashCodeN titleN DONE. - */ - public static Window[] loadWindows(IHvDevice hvDevice, IDevice device) { - ArrayList<Window> windows = new ArrayList<Window>(); - DeviceConnection connection = null; - ViewServerInfo serverInfo = getViewServerInfo(device); - try { - connection = new DeviceConnection(device); - connection.sendCommand("LIST"); //$NON-NLS-1$ - BufferedReader in = connection.getInputStream(); - String line; - while ((line = in.readLine()) != null) { - if ("DONE.".equalsIgnoreCase(line)) { //$NON-NLS-1$ - break; - } - - int index = line.indexOf(' '); - if (index != -1) { - String windowId = line.substring(0, index); - - int id; - if (serverInfo.serverVersion > 2) { - id = (int) Long.parseLong(windowId, 16); - } else { - id = Integer.parseInt(windowId, 16); - } - - Window w = new Window(hvDevice, line.substring(index + 1), id); - windows.add(w); - } - } - // Automatic refreshing of windows was added in protocol version 3. - // Before, the user needed to specify explicitly that he wants to - // get the focused window, which was done using a special type of - // window with hash code -1. - if (serverInfo.protocolVersion < 3) { - windows.add(Window.getFocusedWindow(hvDevice)); - } - } catch (Exception e) { - Log.e(TAG, "Unable to load the window list from device " + device); - } finally { - if (connection != null) { - connection.close(); - } - } - // The server returns the list of windows from the window at the bottom - // to the top. We want the reverse order to put the top window on top of - // the list. - Window[] returnValue = new Window[windows.size()]; - for (int i = windows.size() - 1; i >= 0; i--) { - returnValue[returnValue.length - i - 1] = windows.get(i); - } - return returnValue; - } - - /* - * This gets the hash code of the window that has focus. Only works with - * protocol version 3 and above. - */ - public static int getFocusedWindow(IDevice device) { - DeviceConnection connection = null; - try { - connection = new DeviceConnection(device); - connection.sendCommand("GET_FOCUS"); //$NON-NLS-1$ - String line = connection.getInputStream().readLine(); - if (line == null || line.length() == 0) { - return -1; - } - return (int) Long.parseLong(line.substring(0, line.indexOf(' ')), 16); - } catch (Exception e) { - Log.e(TAG, "Unable to get the focused window from device " + device); - } finally { - if (connection != null) { - connection.close(); - } - } - return -1; - } - - public static ViewNode loadWindowData(Window window) { - DeviceConnection connection = null; - try { - connection = new DeviceConnection(window.getDevice()); - connection.sendCommand("DUMP " + window.encode()); //$NON-NLS-1$ - BufferedReader in = connection.getInputStream(); - ViewNode currentNode = parseViewHierarchy(in, window); - ViewServerInfo serverInfo = getViewServerInfo(window.getDevice()); - if (serverInfo != null) { - currentNode.protocolVersion = serverInfo.protocolVersion; - } - return currentNode; - } catch (Exception e) { - Log.e(TAG, "Unable to load window data for window " + window.getTitle() + " on device " - + window.getDevice()); - Log.e(TAG, e.getMessage()); - } finally { - if (connection != null) { - connection.close(); - } - } - return null; - } - - public static ViewNode parseViewHierarchy(BufferedReader in, Window window) { - ViewNode currentNode = null; - int currentDepth = -1; - String line; - try { - while ((line = in.readLine()) != null) { - if ("DONE.".equalsIgnoreCase(line)) { - break; - } - int depth = 0; - while (line.charAt(depth) == ' ') { - depth++; - } - while (depth <= currentDepth) { - if (currentNode != null) { - currentNode = currentNode.parent; - } - currentDepth--; - } - currentNode = new ViewNode(window, currentNode, line.substring(depth)); - currentDepth = depth; - } - } catch (IOException e) { - Log.e(TAG, "Error reading view hierarchy stream: " + e.getMessage()); - return null; - } - if (currentNode == null) { - return null; - } - while (currentNode.parent != null) { - currentNode = currentNode.parent; - } - - return currentNode; - } - - public static boolean loadProfileData(Window window, ViewNode viewNode) { - DeviceConnection connection = null; - try { - connection = new DeviceConnection(window.getDevice()); - connection.sendCommand("PROFILE " + window.encode() + " " + viewNode.toString()); //$NON-NLS-1$ - BufferedReader in = connection.getInputStream(); - int protocol; - synchronized (sViewServerInfo) { - protocol = sViewServerInfo.get(window.getDevice()).protocolVersion; - } - if (protocol < 3) { - return loadProfileData(viewNode, in); - } else { - boolean ret = loadProfileDataRecursive(viewNode, in); - if (ret) { - viewNode.setProfileRatings(); - } - return ret; - } - } catch (Exception e) { - Log.e(TAG, "Unable to load profiling data for window " + window.getTitle() - + " on device " + window.getDevice()); - } finally { - if (connection != null) { - connection.close(); - } - } - return false; - } - - private static boolean loadProfileData(ViewNode node, BufferedReader in) throws IOException { - String line; - if ((line = in.readLine()) == null || line.equalsIgnoreCase("-1 -1 -1") //$NON-NLS-1$ - || line.equalsIgnoreCase("DONE.")) { //$NON-NLS-1$ - return false; - } - String[] data = line.split(" "); - node.measureTime = (Long.parseLong(data[0]) / 1000.0) / 1000.0; - node.layoutTime = (Long.parseLong(data[1]) / 1000.0) / 1000.0; - node.drawTime = (Long.parseLong(data[2]) / 1000.0) / 1000.0; - return true; - } - - public static boolean loadProfileDataRecursive(ViewNode node, BufferedReader in) - throws IOException { - if (!loadProfileData(node, in)) { - return false; - } - for (int i = 0; i < node.children.size(); i++) { - if (!loadProfileDataRecursive(node.children.get(i), in)) { - return false; - } - } - return true; - } - - public static Image loadCapture(Window window, ViewNode viewNode) { - DeviceConnection connection = null; - try { - connection = new DeviceConnection(window.getDevice()); - connection.getSocket().setSoTimeout(5000); - connection.sendCommand("CAPTURE " + window.encode() + " " + viewNode.toString()); //$NON-NLS-1$ - return new Image(Display.getDefault(), connection.getSocket().getInputStream()); - } catch (Exception e) { - Log.e(TAG, "Unable to capture data for node " + viewNode + " in window " - + window.getTitle() + " on device " + window.getDevice()); - } finally { - if (connection != null) { - connection.close(); - } - } - return null; - } - - public static PsdFile captureLayers(Window window) { - DeviceConnection connection = null; - DataInputStream in = null; - - try { - connection = new DeviceConnection(window.getDevice()); - connection.sendCommand("CAPTURE_LAYERS " + window.encode()); //$NON-NLS-1$ - - in = - new DataInputStream(new BufferedInputStream(connection.getSocket() - .getInputStream())); - - return parsePsd(in); - } catch (IOException e) { - Log.e(TAG, "Unable to capture layers for window " + window.getTitle() + " on device " - + window.getDevice()); - } finally { - if (in != null) { - try { - in.close(); - } catch (Exception ex) { - } - } - - if (connection != null) { - connection.close(); - } - } - - return null; - } - - public static PsdFile parsePsd(DataInputStream in) throws IOException { - int width = in.readInt(); - int height = in.readInt(); - - PsdFile psd = new PsdFile(width, height); - - while (readLayer(in, psd)) { - } - - return psd; - } - - private static boolean readLayer(DataInputStream in, PsdFile psd) { - try { - if (in.read() == 2) { - return false; - } - String name = in.readUTF(); - boolean visible = in.read() == 1; - int x = in.readInt(); - int y = in.readInt(); - int dataSize = in.readInt(); - - byte[] data = new byte[dataSize]; - int read = 0; - while (read < dataSize) { - read += in.read(data, read, dataSize - read); - } - - ByteArrayInputStream arrayIn = new ByteArrayInputStream(data); - BufferedImage chunk = ImageIO.read(arrayIn); - - // Ensure the image is in the right format - BufferedImage image = - new BufferedImage(chunk.getWidth(), chunk.getHeight(), - BufferedImage.TYPE_INT_ARGB); - Graphics2D g = image.createGraphics(); - g.drawImage(chunk, null, 0, 0); - g.dispose(); - - psd.addLayer(name, image, new Point(x, y), visible); - - return true; - } catch (Exception e) { - return false; - } - } - - public static void invalidateView(ViewNode viewNode) { - DeviceConnection connection = null; - try { - connection = new DeviceConnection(viewNode.window.getDevice()); - connection.sendCommand("INVALIDATE " + viewNode.window.encode() + " " + viewNode); //$NON-NLS-1$ - } catch (Exception e) { - Log.e(TAG, "Unable to invalidate view " + viewNode + " in window " + viewNode.window - + " on device " + viewNode.window.getDevice()); - } finally { - if (connection != null) { - connection.close(); - } - } - } - - public static void requestLayout(ViewNode viewNode) { - DeviceConnection connection = null; - try { - connection = new DeviceConnection(viewNode.window.getDevice()); - connection.sendCommand("REQUEST_LAYOUT " + viewNode.window.encode() + " " + viewNode); //$NON-NLS-1$ - } catch (Exception e) { - Log.e(TAG, "Unable to request layout for node " + viewNode + " in window " - + viewNode.window + " on device " + viewNode.window.getDevice()); - } finally { - if (connection != null) { - connection.close(); - } - } - } - - public static void outputDisplayList(ViewNode viewNode) { - DeviceConnection connection = null; - try { - connection = new DeviceConnection(viewNode.window.getDevice()); - connection.sendCommand("OUTPUT_DISPLAYLIST " + - viewNode.window.encode() + " " + viewNode); //$NON-NLS-1$ - } catch (Exception e) { - Log.e(TAG, "Unable to dump displaylist for node " + viewNode + " in window " - + viewNode.window + " on device " + viewNode.window.getDevice()); - } finally { - if (connection != null) { - connection.close(); - } - } - } - -} diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/DeviceConnection.java b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/DeviceConnection.java deleted file mode 100644 index f750d5c..0000000 --- a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/DeviceConnection.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2010 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.hierarchyviewerlib.device; - -import com.android.ddmlib.IDevice; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.nio.channels.SocketChannel; - -/** - * This class is used for connecting to a device in debug mode running the view - * server. - */ -public class DeviceConnection { - - // Now a socket channel, since socket channels are friendly with interrupts. - private SocketChannel mSocketChannel; - - private BufferedReader mIn; - - private BufferedWriter mOut; - - public DeviceConnection(IDevice device) throws IOException { - mSocketChannel = SocketChannel.open(); - int port = DeviceBridge.getDeviceLocalPort(device); - - if (port == -1) { - throw new IOException(); - } - - mSocketChannel.connect(new InetSocketAddress("127.0.0.1", port)); //$NON-NLS-1$ - mSocketChannel.socket().setSoTimeout(40000); - } - - public BufferedReader getInputStream() throws IOException { - if (mIn == null) { - mIn = new BufferedReader(new InputStreamReader(mSocketChannel.socket().getInputStream())); - } - return mIn; - } - - public BufferedWriter getOutputStream() throws IOException { - if (mOut == null) { - mOut = - new BufferedWriter(new OutputStreamWriter(mSocketChannel.socket() - .getOutputStream())); - } - return mOut; - } - - public Socket getSocket() { - return mSocketChannel.socket(); - } - - public void sendCommand(String command) throws IOException { - BufferedWriter out = getOutputStream(); - out.write(command); - out.newLine(); - out.flush(); - } - - public void close() { - try { - if (mIn != null) { - mIn.close(); - } - } catch (IOException e) { - } - try { - if (mOut != null) { - mOut.close(); - } - } catch (IOException e) { - } - try { - mSocketChannel.close(); - } catch (IOException e) { - } - } -} diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/HvDeviceFactory.java b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/HvDeviceFactory.java deleted file mode 100644 index 24a5a4f..0000000 --- a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/HvDeviceFactory.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2013 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.hierarchyviewerlib.device; - -import com.android.ddmlib.Client; -import com.android.ddmlib.ClientData; -import com.android.ddmlib.IDevice; - -public class HvDeviceFactory { - private static final String sHvProtoEnvVar = - System.getenv("ANDROID_HVPROTO"); //$NON-NLS-1$ - - public static IHvDevice create(IDevice device) { - // default to old mechanism until the new one is fully tested - if (sHvProtoEnvVar == null || - !"ddm".equalsIgnoreCase(sHvProtoEnvVar)) { //$NON-NLS-1$ - return new ViewServerDevice(device); - } - - // Wait for a few seconds after the device has been connected to - // allow all the clients to be initialized. Specifically, we need to wait - // until the client data is filled with the list of features supported - // by the client. - try { - Thread.sleep(2000); - } catch (InterruptedException e) { - // ignore - } - - boolean ddmViewHierarchy = false; - - // see if any of the clients on the device support view hierarchy via DDMS - for (Client c : device.getClients()) { - ClientData cd = c.getClientData(); - if (cd != null && cd.hasFeature(ClientData.FEATURE_VIEW_HIERARCHY)) { - ddmViewHierarchy = true; - break; - } - } - - return ddmViewHierarchy ? new DdmViewDebugDevice(device) : new ViewServerDevice(device); - } -} diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/IHvDevice.java b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/IHvDevice.java deleted file mode 100644 index 6f1fd37..0000000 --- a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/IHvDevice.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2013 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.hierarchyviewerlib.device; - -import com.android.ddmlib.IDevice; -import com.android.hierarchyviewerlib.device.WindowUpdater.IWindowChangeListener; -import com.android.hierarchyviewerlib.models.ViewNode; -import com.android.hierarchyviewerlib.models.Window; -import com.android.hierarchyviewerlib.ui.util.PsdFile; - -import org.eclipse.swt.graphics.Image; - -import java.util.List; - -/** Represents a device that can perform view debug operations. */ -public interface IHvDevice { - /** - * Initializes view debugging on the device. - * @return true if the on device component was successfully initialized - */ - boolean initializeViewDebug(); - boolean reloadWindows(); - - void terminateViewDebug(); - boolean isViewDebugEnabled(); - boolean supportsDisplayListDump(); - - Window[] getWindows(); - int getFocusedWindow(); - - IDevice getDevice(); - - Image getScreenshotImage(); - ViewNode loadWindowData(Window window); - void loadProfileData(Window window, ViewNode viewNode); - Image loadCapture(Window window, ViewNode viewNode); - PsdFile captureLayers(Window window); - void invalidateView(ViewNode viewNode); - void requestLayout(ViewNode viewNode); - void outputDisplayList(ViewNode viewNode); - - boolean isViewUpdateEnabled(); - void invokeViewMethod(Window window, ViewNode viewNode, String method, List<?> args); - boolean setLayoutParameter(Window window, ViewNode viewNode, String property, int value); - - void addWindowChangeListener(IWindowChangeListener l); - void removeWindowChangeListener(IWindowChangeListener l); -} diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/ViewServerDevice.java b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/ViewServerDevice.java deleted file mode 100644 index 4445e9a..0000000 --- a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/ViewServerDevice.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (C) 2013 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.hierarchyviewerlib.device; - -import com.android.ddmlib.IDevice; -import com.android.ddmlib.Log; -import com.android.hierarchyviewerlib.device.DeviceBridge.ViewServerInfo; -import com.android.hierarchyviewerlib.device.WindowUpdater.IWindowChangeListener; -import com.android.hierarchyviewerlib.models.ViewNode; -import com.android.hierarchyviewerlib.models.Window; -import com.android.hierarchyviewerlib.ui.util.PsdFile; - -import org.eclipse.swt.graphics.Image; - -import java.util.List; - -public class ViewServerDevice extends AbstractHvDevice { - static final String TAG = "ViewServerDevice"; - - final IDevice mDevice; - private ViewServerInfo mViewServerInfo; - private Window[] mWindows; - - public ViewServerDevice(IDevice device) { - mDevice = device; - } - - @Override - public boolean initializeViewDebug() { - if (!mDevice.isOnline()) { - return false; - } - - DeviceBridge.setupDeviceForward(mDevice); - - return reloadWindows(); - } - - @Override - public boolean reloadWindows() { - if (!DeviceBridge.isViewServerRunning(mDevice)) { - if (!DeviceBridge.startViewServer(mDevice)) { - Log.e(TAG, "Unable to debug device: " + mDevice.getName()); - DeviceBridge.removeDeviceForward(mDevice); - return false; - } - } - - mViewServerInfo = DeviceBridge.loadViewServerInfo(mDevice); - if (mViewServerInfo == null) { - return false; - } - - mWindows = DeviceBridge.loadWindows(this, mDevice); - return true; - } - - @Override - public boolean supportsDisplayListDump() { - return mViewServerInfo != null && mViewServerInfo.protocolVersion >= 4; - } - - @Override - public void terminateViewDebug() { - DeviceBridge.removeDeviceForward(mDevice); - DeviceBridge.removeViewServerInfo(mDevice); - } - - @Override - public boolean isViewDebugEnabled() { - return mViewServerInfo != null; - } - - @Override - public Window[] getWindows() { - return mWindows; - } - - @Override - public int getFocusedWindow() { - return DeviceBridge.getFocusedWindow(mDevice); - } - - @Override - public IDevice getDevice() { - return mDevice; - } - - @Override - public ViewNode loadWindowData(Window window) { - return DeviceBridge.loadWindowData(window); - } - - @Override - public void loadProfileData(Window window, ViewNode viewNode) { - DeviceBridge.loadProfileData(window, viewNode); - } - - @Override - public Image loadCapture(Window window, ViewNode viewNode) { - return DeviceBridge.loadCapture(window, viewNode); - } - - @Override - public PsdFile captureLayers(Window window) { - return DeviceBridge.captureLayers(window); - } - - @Override - public void invalidateView(ViewNode viewNode) { - DeviceBridge.invalidateView(viewNode); - } - - @Override - public void requestLayout(ViewNode viewNode) { - DeviceBridge.requestLayout(viewNode); - } - - @Override - public void outputDisplayList(ViewNode viewNode) { - DeviceBridge.outputDisplayList(viewNode); - } - - @Override - public void addWindowChangeListener(IWindowChangeListener l) { - if (mViewServerInfo != null && mViewServerInfo.protocolVersion >= 3) { - WindowUpdater.startListenForWindowChanges(l, mDevice); - } - } - - @Override - public void removeWindowChangeListener(IWindowChangeListener l) { - if (mViewServerInfo != null && mViewServerInfo.protocolVersion >= 3) { - WindowUpdater.stopListenForWindowChanges(l, mDevice); - } - } - - @Override - public boolean isViewUpdateEnabled() { - return false; - } - - @Override - public void invokeViewMethod(Window window, ViewNode viewNode, String method, - List<?> args) { - // not supported - } - - @Override - public boolean setLayoutParameter(Window window, ViewNode viewNode, String property, - int value) { - // not supported - return false; - } -} diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/WindowUpdater.java b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/WindowUpdater.java deleted file mode 100644 index a67d400..0000000 --- a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/WindowUpdater.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (C) 2010 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.hierarchyviewerlib.device; - -import com.android.ddmlib.IDevice; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; - -/** - * This class handles automatic updating of the list of windows in the device - * selector for device with protocol version 3 or above of the view server. It - * connects to the devices, keeps the connection open and listens for messages. - * It notifies all it's listeners of changes. - */ -public class WindowUpdater { - private static HashMap<IDevice, ArrayList<IWindowChangeListener>> sWindowChangeListeners = - new HashMap<IDevice, ArrayList<IWindowChangeListener>>(); - - private static HashMap<IDevice, Thread> sListeningThreads = new HashMap<IDevice, Thread>(); - - public static interface IWindowChangeListener { - public void windowsChanged(IDevice device); - - public void focusChanged(IDevice device); - } - - public static void terminate() { - synchronized (sListeningThreads) { - for (IDevice device : sListeningThreads.keySet()) { - sListeningThreads.get(device).interrupt(); - - } - } - } - - public static void startListenForWindowChanges(IWindowChangeListener listener, IDevice device) { - synchronized (sWindowChangeListeners) { - // In this case, a listening thread already exists, so we don't need - // to create another one. - if (sWindowChangeListeners.containsKey(device)) { - sWindowChangeListeners.get(device).add(listener); - return; - } - ArrayList<IWindowChangeListener> listeners = new ArrayList<IWindowChangeListener>(); - listeners.add(listener); - sWindowChangeListeners.put(device, listeners); - } - // Start listening - Thread listeningThread = new Thread(new WindowChangeMonitor(device)); - synchronized (sListeningThreads) { - sListeningThreads.put(device, listeningThread); - } - listeningThread.start(); - } - - public static void stopListenForWindowChanges(IWindowChangeListener listener, IDevice device) { - synchronized (sWindowChangeListeners) { - ArrayList<IWindowChangeListener> listeners = sWindowChangeListeners.get(device); - if (listeners == null) { - return; - } - listeners.remove(listener); - // There are more listeners, so don't stop the listening thread. - if (listeners.size() != 0) { - return; - } - sWindowChangeListeners.remove(device); - } - // Everybody left, so the party's over! - Thread listeningThread; - synchronized (sListeningThreads) { - listeningThread = sListeningThreads.get(device); - sListeningThreads.remove(device); - } - listeningThread.interrupt(); - } - - private static IWindowChangeListener[] getWindowChangeListenersAsArray(IDevice device) { - IWindowChangeListener[] listeners; - synchronized (sWindowChangeListeners) { - ArrayList<IWindowChangeListener> windowChangeListenerList = - sWindowChangeListeners.get(device); - if (windowChangeListenerList == null) { - return null; - } - listeners = - windowChangeListenerList - .toArray(new IWindowChangeListener[windowChangeListenerList.size()]); - } - return listeners; - } - - public static void notifyWindowsChanged(IDevice device) { - IWindowChangeListener[] listeners = getWindowChangeListenersAsArray(device); - if (listeners != null) { - for (int i = 0; i < listeners.length; i++) { - listeners[i].windowsChanged(device); - } - } - } - - public static void notifyFocusChanged(IDevice device) { - IWindowChangeListener[] listeners = getWindowChangeListenersAsArray(device); - if (listeners != null) { - for (int i = 0; i < listeners.length; i++) { - listeners[i].focusChanged(device); - } - } - } - - private static class WindowChangeMonitor implements Runnable { - private IDevice device; - - public WindowChangeMonitor(IDevice device) { - this.device = device; - } - - @Override - public void run() { - while (!Thread.currentThread().isInterrupted()) { - DeviceConnection connection = null; - try { - connection = new DeviceConnection(device); - connection.sendCommand("AUTOLIST"); - String line; - while (!Thread.currentThread().isInterrupted() - && (line = connection.getInputStream().readLine()) != null) { - if (line.equalsIgnoreCase("LIST UPDATE")) { - notifyWindowsChanged(device); - } else if (line.equalsIgnoreCase("FOCUS UPDATE")) { - notifyFocusChanged(device); - } - } - - } catch (IOException e) { - } finally { - if (connection != null) { - connection.close(); - } - } - } - } - } -} |