diff options
Diffstat (limited to 'src/plugins/devices.services/src/com/motorola')
23 files changed, 2834 insertions, 0 deletions
diff --git a/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/DeviceServicesPlugin.java b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/DeviceServicesPlugin.java new file mode 100644 index 0000000..e568e18 --- /dev/null +++ b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/DeviceServicesPlugin.java @@ -0,0 +1,477 @@ +/*
+ * Copyright (C) 2012 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.motorola.studio.android.devices.services;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.sequoyah.device.framework.factory.DeviceTypeRegistry;
+import org.eclipse.sequoyah.device.framework.model.IDeviceType;
+import org.eclipse.sequoyah.device.framework.model.IService;
+import org.eclipse.sequoyah.device.framework.model.handler.IServiceHandler;
+import org.eclipse.sequoyah.device.framework.model.handler.ServiceHandler;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchListener;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.console.ConsolePlugin;
+import org.eclipse.ui.console.IConsole;
+import org.eclipse.ui.console.IOConsole;
+import org.eclipse.ui.console.IOConsoleInputStream;
+import org.eclipse.ui.console.IOConsoleOutputStream;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+import com.motorola.studio.android.common.log.StudioLogger;
+import com.motorola.studio.android.devices.services.console.ADBShellHandler;
+import com.motorola.studio.android.devices.services.console.EmulatorConsoleHandler;
+import com.motorola.studio.android.emulator.EmulatorPlugin;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class DeviceServicesPlugin extends AbstractUIPlugin
+{
+
+ public static final String PLUGIN_ID = "com.motorola.studio.android.devices.services";
+
+ public static final String DEPLOY_SERVICE_ID =
+ "com.motorola.studio.android.devices.services.deployService";
+
+ public static final String UNINSTALL_APP_SERVICE_ID =
+ "com.motorola.studio.android.devices.services.uninstallAppService";
+
+ private static ServiceHandler deployServiceHandler = null;
+
+ private static ServiceHandler uninstallAppServiceHandler = null;
+
+ public static final boolean IS_WIN32 = Platform.getOS().equals(Platform.OS_WIN32);
+
+ private static String EMULATOR_CONSOLE_SERVICE_ID =
+ "com.motorola.studio.android.devices.services.emulatorConsole";
+
+ private static String ADB_SHELL_SERVICE_ID =
+ "com.motorola.studio.android.devices.services.adbShell";
+
+ private static DeviceServicesPlugin plugin;
+
+ private static final String SCREENSHOT_SERVICE_ID = PLUGIN_ID + ".takescreenshot";
+
+ private static final String MONKEY_SERVICE_ID = PLUGIN_ID + ".monkey";
+
+ private static ServiceHandler screenshotServiceHandler = null;
+
+ private static ServiceHandler monkeyServiceHandler = null;
+
+ private static ServiceHandler adbShellServiceHandler = null;
+
+ private static ServiceHandler emulatorConsoleServiceHandler = null;
+
+ public static final String ANDROID_LANG_SERVICE_ID = PLUGIN_ID + ".changeLanguageService";
+
+ public static final String LANG_PAGE_CONTEXT_HELP_ID = PLUGIN_ID + ".langPage";
+
+ private static Collection<IConsoleKilledListener> listeners =
+ new ArrayList<IConsoleKilledListener>();
+
+ private final IWorkbenchListener workbenchListener = new IWorkbenchListener()
+ {
+
+ // killllll all consoles
+ public boolean preShutdown(IWorkbench workbench, boolean forced)
+ {
+ List<IConsole> consolesToClose = new ArrayList<IConsole>();
+ List<IConsoleKilledListener> copy = new ArrayList<IConsoleKilledListener>(listeners);
+ for (IConsole console : ConsolePlugin.getDefault().getConsoleManager().getConsoles()
+ .clone())
+ {
+ if (console.getName().contains(EmulatorConsoleHandler.CONSOLE_NAME)
+ || console.getName().contains(ADBShellHandler.CONSOLE_NAME))
+ {
+ for (IConsoleKilledListener listener : copy)
+ {
+ listener.consoleKilled(console.getName());
+ }
+
+ consolesToClose.add(console);
+ }
+
+ }
+ if (consolesToClose.size() > 0)
+ {
+
+ ConsolePlugin.getDefault().getConsoleManager()
+ .removeConsoles(consolesToClose.toArray(new IConsole[0]));
+ }
+ return true;
+ }
+
+ public void postShutdown(IWorkbench workbench)
+ {
+ //do nothing;
+ }
+ };
+
+ public interface IConsoleKilledListener
+ {
+ void consoleKilled(String consoleName);
+ }
+
+ public static void addConsoleKilledListener(IConsoleKilledListener listener)
+ {
+ /*
+ * Keep the entire list, even if elements are the same object.
+ * This will ensure that the last console killed will have their proper listener.
+ */
+ if (!listeners.contains(listener))
+ {
+ listeners.add(listener);
+ }
+ }
+
+ public static void removeConsoleKilledListener(IConsoleKilledListener listener)
+ {
+ listeners.remove(listener);
+ }
+
+ public DeviceServicesPlugin()
+ {
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void start(BundleContext context) throws Exception
+ {
+ StudioLogger.debug(DeviceServicesPlugin.class,
+ "Starting MOTODEV Android Device Services Plugin...");
+
+ super.start(context);
+ plugin = this;
+ PlatformUI.getWorkbench().addWorkbenchListener(workbenchListener);
+
+ StudioLogger.debug(DeviceServicesPlugin.class,
+ "MOTODEV Android Device Services Plugin started.");
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void stop(BundleContext context) throws Exception
+ {
+ PlatformUI.getWorkbench().removeWorkbenchListener(workbenchListener);
+ plugin = null;
+ super.stop(context);
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static DeviceServicesPlugin getDefault()
+ {
+ return plugin;
+ }
+
+ /**
+ * Creates a console for a process
+ *
+ * @param p The process
+ */
+ public static void redirectProcessStreamsToConsole(Process p, String consoleName)
+ {
+ InputStream processIn = p.getInputStream();
+ OutputStream processOut = p.getOutputStream();
+ redirectStreamsToConsole(processIn, processOut, consoleName);
+ }
+
+ /**
+ * Creates a console for a process
+ *
+ * @param p The process
+ */
+ public static void redirectStreamsToConsole(final InputStream in, final OutputStream out,
+ final String consoleName)
+ {
+ final IOConsole console = new IOConsole(consoleName, null);
+
+ console.activate();
+ ConsolePlugin.getDefault().getConsoleManager().addConsoles(new IConsole[]
+ {
+ console
+ });
+
+ final IOConsoleOutputStream consoleOut = console.newOutputStream();
+ final IOConsoleInputStream consoleIn = console.getInputStream();
+
+ new Thread(new Runnable()
+ {
+ public void run()
+ {
+ boolean carriageReturn = false;
+
+ while (true)
+ {
+ try
+ {
+ int byteRead = in.read();
+ if (byteRead == -1)
+ {
+ throw new Exception();
+ }
+
+ if (carriageReturn && (byteRead != 13))
+ {
+ consoleOut.write(13);
+ consoleOut.write(byteRead);
+ carriageReturn = false;
+ }
+ else if (!carriageReturn && (byteRead == 13))
+ {
+ carriageReturn = true;
+ }
+ else
+ {
+ consoleOut.write(byteRead);
+ carriageReturn = false;
+ }
+ consoleOut.flush();
+ }
+ catch (Exception e)
+ {
+ ConsolePlugin.getDefault().getConsoleManager()
+ .removeConsoles(new IConsole[]
+ {
+ console
+ });
+
+ Collection<IConsoleKilledListener> cloneListeners =
+ new ArrayList<IConsoleKilledListener>(listeners);
+ for (IConsoleKilledListener listener : cloneListeners)
+ {
+ listener.consoleKilled(consoleName);
+ }
+
+ break;
+ }
+ }
+ }
+ }).start();
+
+ new Thread(new Runnable()
+ {
+ public void run()
+ {
+ while (true)
+ {
+ try
+ {
+ int byteRead = consoleIn.read();
+ out.write(byteRead);
+ out.flush();
+ }
+ catch (Exception e)
+ {
+ break;
+ }
+ }
+ }
+ }).start();
+ }
+
+ /**
+ * Retrieves the adb shell service handler.
+ *
+ * @return The currently registered stop service handler, or <null> if no handler is registered.
+ */
+ public static ServiceHandler getADBShellServiceHandler()
+ {
+ if ((adbShellServiceHandler == null) && (ADB_SHELL_SERVICE_ID != null))
+ {
+ // find the appropriate stop service handler
+ IDeviceType device =
+
+ DeviceTypeRegistry.getInstance().getDeviceTypeById(EmulatorPlugin.DEVICE_ID);
+ List<IService> services = device.getServices();
+
+ for (IService service : services)
+ {
+ IServiceHandler handler = service.getHandler();
+ if (handler.getService().getId().equals(ADB_SHELL_SERVICE_ID))
+ {
+ adbShellServiceHandler = (ServiceHandler) handler;
+ break;
+ }
+ }
+ }
+ return adbShellServiceHandler;
+ }
+
+ /**
+ * Retrieves the emulator console service handler.
+ *
+ * @return The currently registered stop service handler, or <null> if no handler is registered.
+ */
+ public static ServiceHandler getEmulatorConsoleServiceHandler()
+ {
+ if ((emulatorConsoleServiceHandler == null) && (EMULATOR_CONSOLE_SERVICE_ID != null))
+ {
+ // find the appropriate stop service handler
+ IDeviceType device =
+ DeviceTypeRegistry.getInstance().getDeviceTypeById(EmulatorPlugin.DEVICE_ID);
+ List<IService> services = device.getServices();
+ for (IService service : services)
+ {
+ IServiceHandler handler = service.getHandler();
+ if (handler.getService().getId().equals(EMULATOR_CONSOLE_SERVICE_ID))
+ {
+ emulatorConsoleServiceHandler = (ServiceHandler) handler;
+ break;
+ }
+ }
+ }
+
+ return emulatorConsoleServiceHandler;
+ }
+
+ /**
+ * Creates and returns a new image descriptor for an image file in this plug-in.
+ * @param path the relative path of the image file, relative to the root of the plug-in; the path must be legal
+ * @return an image descriptor, or null if no image could be found
+ */
+ public static ImageDescriptor getImageDescriptor(String path)
+ {
+ return imageDescriptorFromPlugin(PLUGIN_ID, path);
+ }
+
+ /**
+ * Retrieves the deploy service handler.
+ *
+ * @return The currently registered stop service handler, or <null> if no handler is registered.
+ */
+ public static ServiceHandler getDeployServiceHandler()
+ {
+ if ((deployServiceHandler == null) && (DEPLOY_SERVICE_ID != null))
+ {
+ // find the appropriate stop service handler
+ IDeviceType device =
+ DeviceTypeRegistry.getInstance().getDeviceTypeById(EmulatorPlugin.DEVICE_ID);
+ List<IService> services = device.getServices();
+ for (IService service : services)
+ {
+ IServiceHandler handler = service.getHandler();
+ if (handler.getService().getId().equals(DEPLOY_SERVICE_ID))
+ {
+ deployServiceHandler = (ServiceHandler) handler;
+ break;
+ }
+ }
+ }
+
+ return deployServiceHandler;
+ }
+
+ /**
+ * Retrieves the deploy service handler.
+ *
+ * @return The currently registered stop service handler, or <null> if no handler is registered.
+ */
+ public static ServiceHandler getUninstallAppServiceHandler()
+ {
+ if ((uninstallAppServiceHandler == null) && (UNINSTALL_APP_SERVICE_ID != null))
+ {
+ // find the appropriate stop service handler
+ IDeviceType device =
+ DeviceTypeRegistry.getInstance().getDeviceTypeById(EmulatorPlugin.DEVICE_ID);
+ List<IService> services = device.getServices();
+ for (IService service : services)
+ {
+ IServiceHandler handler = service.getHandler();
+ if (handler.getService().getId().equals(UNINSTALL_APP_SERVICE_ID))
+ {
+ uninstallAppServiceHandler = (ServiceHandler) handler;
+ break;
+ }
+ }
+ }
+
+ return uninstallAppServiceHandler;
+ }
+
+ /**
+ * Retrieves the deploy service handler.
+ *
+ * @return The currently registered stop service handler, or <null> if no handler is registered.
+ */
+ public static ServiceHandler getScreenshotServiceHandler()
+ {
+ if ((screenshotServiceHandler == null) && (SCREENSHOT_SERVICE_ID != null))
+ {
+ // find the appropriate stop service handler
+ IDeviceType device =
+ DeviceTypeRegistry.getInstance().getDeviceTypeById(EmulatorPlugin.DEVICE_ID);
+ List<IService> services = device.getServices();
+ for (IService service : services)
+ {
+ IServiceHandler handler = service.getHandler();
+ if (handler.getService().getId().equals(SCREENSHOT_SERVICE_ID))
+ {
+ screenshotServiceHandler = (ServiceHandler) handler;
+ break;
+ }
+ }
+ }
+
+ return screenshotServiceHandler;
+ }
+
+ /**
+ * Retrieves the monkey service handler.
+ *
+ * @return The currently registered stop service handler, or <null> if no handler is registered.
+ */
+ public static ServiceHandler getMonkeyServiceHandler()
+ {
+ if ((monkeyServiceHandler == null) && (MONKEY_SERVICE_ID != null))
+ {
+ // find the appropriate stop service handler
+ IDeviceType device =
+ DeviceTypeRegistry.getInstance().getDeviceTypeById(EmulatorPlugin.DEVICE_ID);
+ List<IService> services = device.getServices();
+ IServiceHandler handler = null;
+ for (IService service : services)
+ {
+ handler = service.getHandler();
+ if (handler.getService().getId().equals(MONKEY_SERVICE_ID))
+ {
+ monkeyServiceHandler = (ServiceHandler) handler;
+ break;
+ }
+ }
+ }
+
+ return monkeyServiceHandler;
+ }
+}
diff --git a/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/console/ADBShellCommand.java b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/console/ADBShellCommand.java new file mode 100644 index 0000000..b9f0cad --- /dev/null +++ b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/console/ADBShellCommand.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2012 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.motorola.studio.android.devices.services.console; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.sequoyah.device.common.utilities.exception.SequoyahException; +import org.eclipse.sequoyah.device.framework.model.IInstance; + +import com.motorola.studio.android.devices.services.DeviceServicesPlugin; +import com.motorola.studio.android.emulator.core.model.IAndroidEmulatorInstance; +import com.motorola.studio.android.emulator.ui.view.AbstractAndroidView; + +public class ADBShellCommand extends AbstractHandler +{ + + public Object execute(ExecutionEvent event) throws ExecutionException + { + IAndroidEmulatorInstance instance = AbstractAndroidView.getActiveInstance(); + if (instance instanceof IInstance) + { + try + { + DeviceServicesPlugin.getADBShellServiceHandler().run((IInstance) instance); + } + catch (SequoyahException e) + { + //do nothing + } + } + return null; + } + +} diff --git a/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/console/ADBShellHandler.java b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/console/ADBShellHandler.java new file mode 100644 index 0000000..9464955 --- /dev/null +++ b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/console/ADBShellHandler.java @@ -0,0 +1,256 @@ +/* + * Copyright (C) 2012 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.motorola.studio.android.devices.services.console; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubMonitor; +import org.eclipse.jface.dialogs.ProgressMonitorDialog; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.sequoyah.device.framework.model.IInstance; +import org.eclipse.sequoyah.device.framework.model.handler.IServiceHandler; +import org.eclipse.sequoyah.device.framework.model.handler.ServiceHandler; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PlatformUI; + +import com.motorola.studio.android.adt.ISerialNumbered; +import com.motorola.studio.android.adt.SdkUtils; +import com.motorola.studio.android.devices.services.DeviceServicesPlugin; +import com.motorola.studio.android.devices.services.DeviceServicesPlugin.IConsoleKilledListener; +import com.motorola.studio.android.devices.services.i18n.ServicesNLS; + +/** + * Class responsible to implement the handler for the service + * "ADB Shell" + */ +public class ADBShellHandler extends ServiceHandler +{ + public static final String CONSOLE_NAME = "ADB Shell"; //$NON-NLS-1$ + + private static final String SERIAL_PARAMETER = "-s"; //$NON-NLS-1$ + + private static final String SHELL_COMMAND = "shell"; //$NON-NLS-1$ + + private static final Map<String, Integer> consolesCache = new HashMap<String, Integer>(); + + private static final Map<String, Process> consolesProcesses = new HashMap<String, Process>(); + + public ADBShellHandler() + { + + } + + /* + * (non-Javadoc) + * @see org.eclipse.sequoyah.device.framework.model.handler.ServiceHandler#newInstance() + */ + @Override + public IServiceHandler newInstance() + { + return new ADBShellHandler(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.sequoyah.device.framework.model.handler.ServiceHandler#runService(org.eclipse.sequoyah.device.framework.model.IInstance, java.util.Map, org.eclipse.core.runtime.IProgressMonitor) + */ + @Override + public IStatus runService(IInstance theInstance, Map<Object, Object> arguments, + IProgressMonitor monitor) + { + IStatus status = Status.OK_STATUS; + List<String> command = new LinkedList<String>(); + final IInstance instance = theInstance; + + File sdkPath = new File(SdkUtils.getSdkPath()); + String adbPath = SdkUtils.getAdbPath(); + File adb = new File(adbPath); + + if ((sdkPath != null) && sdkPath.exists() && sdkPath.isDirectory()) + { + if (adb.exists() && adb.isFile()) + { + if (instance instanceof ISerialNumbered) + { + final String[] serialNumber = new String[1]; + + serialNumber[0] = ((ISerialNumbered) instance).getSerialNumber(); + + if (serialNumber[0] == null) + { + PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() + { + + public void run() + { + ProgressMonitorDialog dialog = + new ProgressMonitorDialog(new Shell(PlatformUI + .getWorkbench().getDisplay())); + try + { + dialog.run(false, false, new IRunnableWithProgress() + { + + public void run(IProgressMonitor monitor) + throws InvocationTargetException, + InterruptedException + { + int limit = 20; + + SubMonitor theMonitor = SubMonitor.convert(monitor); + theMonitor + .beginTask( + ServicesNLS.ADBShellHandler_WaitingDeviceToLoad, + limit); + + int times = 0; + + while ((serialNumber[0] == null) && (times < limit)) + { + theMonitor.worked(1); + Thread.sleep(500); + serialNumber[0] = + ((ISerialNumbered) instance) + .getSerialNumber(); + times++; + } + + theMonitor.setWorkRemaining(0); + } + }); + } + catch (Exception e) + { + //do nothing + } + } + }); + + } + + // Fix a condition that Studio holds the UI thread forever + if (serialNumber[0] == null) + { + status = + new Status(IStatus.ERROR, DeviceServicesPlugin.PLUGIN_ID, + ServicesNLS.ERR_ADBShellHandler_CouldNotExecuteTheAdbShell); + return status; + } + + if (adbPath.contains(" ")) //$NON-NLS-1$ + { + if (DeviceServicesPlugin.IS_WIN32) + { + adbPath = "\"" + adbPath + "\""; //$NON-NLS-1$ //$NON-NLS-2$ + } + else + { + adbPath = adbPath.replace(" ", "\\ "); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + + command.add(adbPath); + command.add(SERIAL_PARAMETER); + command.add(serialNumber[0]); + command.add(SHELL_COMMAND); + + try + { + Integer i = consolesCache.get(serialNumber[0]); + i = (i == null ? 1 : ++i); + consolesCache.put(serialNumber[0], i); + + String[] cmdArray = command.toArray(new String[4]); + StringBuffer sb = new StringBuffer(); + for (String cmd : cmdArray) + { + sb.append(cmd); + sb.append(" "); //$NON-NLS-1$ + } + + Process p = Runtime.getRuntime().exec(cmdArray); + + String consoleName = CONSOLE_NAME + " - " + serialNumber[0]; //$NON-NLS-1$ + + if (i != null) + { + consoleName += " (" + i + ")"; //$NON-NLS-1$ //$NON-NLS-2$ + } + consolesProcesses.put(consoleName, p); + DeviceServicesPlugin.redirectProcessStreamsToConsole(p, consoleName); + DeviceServicesPlugin.addConsoleKilledListener(listener); + } + catch (IOException e) + { + status = + new Status(IStatus.ERROR, DeviceServicesPlugin.PLUGIN_ID, + ServicesNLS.ERR_ADBShellHandler_CouldNotExecuteTheAdbShell, + e); + } + } + + } + else + { + status = + new Status(IStatus.ERROR, DeviceServicesPlugin.PLUGIN_ID, + ServicesNLS.ERR_ADBShellHandler_MissingAdbShell); + } + } + else + { + status = + new Status(IStatus.ERROR, DeviceServicesPlugin.PLUGIN_ID, + ServicesNLS.ERR_ADBShellHandler_AndroidSdkIsNotConfigured); + } + + return status; + } + + /* + * (non-Javadoc) + * @see org.eclipse.sequoyah.device.framework.model.handler.ServiceHandler#updatingService(org.eclipse.sequoyah.device.framework.model.IInstance, org.eclipse.core.runtime.IProgressMonitor) + */ + @Override + public IStatus updatingService(IInstance arg0, IProgressMonitor arg1) + { + return Status.OK_STATUS; + } + + private final IConsoleKilledListener listener = new IConsoleKilledListener() + { + public void consoleKilled(String name) + { + if (consolesProcesses.containsKey(name)) + { + Process p = consolesProcesses.get(name); + p.destroy(); + DeviceServicesPlugin.removeConsoleKilledListener(listener); + consolesProcesses.remove(name); + } + } + }; + +} diff --git a/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/console/EmulatorConsoleCommand.java b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/console/EmulatorConsoleCommand.java new file mode 100644 index 0000000..d827ed0 --- /dev/null +++ b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/console/EmulatorConsoleCommand.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2012 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.motorola.studio.android.devices.services.console; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.sequoyah.device.common.utilities.exception.SequoyahException; +import org.eclipse.sequoyah.device.framework.model.IInstance; + +import com.motorola.studio.android.devices.services.DeviceServicesPlugin; +import com.motorola.studio.android.emulator.core.model.IAndroidEmulatorInstance; +import com.motorola.studio.android.emulator.ui.view.AbstractAndroidView; + +public class EmulatorConsoleCommand extends AbstractHandler +{ + + public Object execute(ExecutionEvent event) throws ExecutionException + { + IAndroidEmulatorInstance instance = AbstractAndroidView.getActiveInstance(); + if (instance instanceof IInstance) + { + try + { + DeviceServicesPlugin.getEmulatorConsoleServiceHandler().run((IInstance) instance); + } + catch (SequoyahException e) + { + //do nothing + } + } + return null; + } + +} diff --git a/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/console/EmulatorConsoleHandler.java b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/console/EmulatorConsoleHandler.java new file mode 100644 index 0000000..c3bf3d9 --- /dev/null +++ b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/console/EmulatorConsoleHandler.java @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2012 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.motorola.studio.android.devices.services.console; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubMonitor; +import org.eclipse.jface.dialogs.ProgressMonitorDialog; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.sequoyah.device.framework.model.IInstance; +import org.eclipse.sequoyah.device.framework.model.handler.IServiceHandler; +import org.eclipse.sequoyah.device.framework.model.handler.ServiceHandler; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PlatformUI; + +import com.motorola.studio.android.adt.ISerialNumbered; +import com.motorola.studio.android.common.utilities.EclipseUtils; +import com.motorola.studio.android.devices.services.DeviceServicesPlugin; +import com.motorola.studio.android.devices.services.DeviceServicesPlugin.IConsoleKilledListener; +import com.motorola.studio.android.devices.services.i18n.ServicesNLS; +import com.motorola.studio.android.utilities.TelnetFrameworkAndroid; + +/** + * Class responsible to implement the handler for the service + * "Emulator Console" + */ +public class EmulatorConsoleHandler extends ServiceHandler +{ + private static final Map<String, Integer> consolesCache = new HashMap<String, Integer>(); + + private static final Map<String, TelnetFrameworkAndroid> telnetsCache = + new HashMap<String, TelnetFrameworkAndroid>(); + + private final IConsoleKilledListener listener = new IConsoleKilledListener() + { + public void consoleKilled(String name) + { + if (telnetsCache.containsKey(name)) + { + TelnetFrameworkAndroid telnet = telnetsCache.get(name); + if (telnet.isConnected()) + { + try + { + telnet.disconnect(); + } + catch (IOException e) + { + EclipseUtils + .showInformationDialog( + ServicesNLS.GEN_Warning, + ServicesNLS.WARN_EmulatorConsoleHandler_CouldNotCloseTheConsoleConnection); + } + } + telnetsCache.remove(name); + DeviceServicesPlugin.removeConsoleKilledListener(listener); + } + } + }; + + public static final String CONSOLE_NAME = "Emulator Console"; + + private static final String LOCALHOST = "localhost"; + + /** + * Constructor + */ + public EmulatorConsoleHandler() + { + + } + + /* + * (non-Javadoc) + * @see org.eclipse.sequoyah.device.framework.model.handler.ServiceHandler#newInstance() + */ + @Override + public IServiceHandler newInstance() + { + return new EmulatorConsoleHandler(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.sequoyah.device.framework.model.handler.ServiceHandler#runService(org.eclipse.sequoyah.device.framework.model.IInstance, java.util.Map, org.eclipse.core.runtime.IProgressMonitor) + */ + @Override + public IStatus runService(final IInstance instance, Map<Object, Object> arguments, + IProgressMonitor monitor) + { + IStatus status = Status.OK_STATUS; + if (instance instanceof ISerialNumbered) + { + // Retrieve the emulator port from its serial number + Pattern pattern = Pattern.compile("emulator-([0-9]+)"); + final String[] serialNumber = new String[1]; + + serialNumber[0] = ((ISerialNumbered) instance).getSerialNumber(); + if (serialNumber[0] == null) + { + PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() + { + + public void run() + { + ProgressMonitorDialog dialog = + new ProgressMonitorDialog(new Shell(PlatformUI.getWorkbench() + .getDisplay())); + try + { + dialog.run(false, false, new IRunnableWithProgress() + { + + public void run(IProgressMonitor monitor) + throws InvocationTargetException, InterruptedException + { + int limit = 20; + + SubMonitor theMonitor = SubMonitor.convert(monitor); + theMonitor.beginTask( + ServicesNLS.ADBShellHandler_WaitingDeviceToLoad, limit); + + int times = 0; + + while ((serialNumber[0] == null) && (times < limit)) + { + theMonitor.worked(1); + Thread.sleep(500); + serialNumber[0] = + ((ISerialNumbered) instance).getSerialNumber(); + times++; + } + + theMonitor.setWorkRemaining(0); + } + }); + } + catch (Exception e) + { + //do nothing + } + } + }); + } + + // Fix a condition that Studio holds the UI thread forever + if (serialNumber[0] == null) + { + status = + new Status(IStatus.ERROR, DeviceServicesPlugin.PLUGIN_ID, + ServicesNLS.ERR_EmulatorConsoleHandler_CouldNotOpenTheConsoleShell); + return status; + } + + Matcher matcher = pattern.matcher(serialNumber[0]); + if (matcher.matches()) + { + String port = matcher.group(1); + final TelnetFrameworkAndroid telnet = new TelnetFrameworkAndroid(); + try + { + Integer i = consolesCache.get(serialNumber[0]); + i = (i == null ? 1 : ++i); + consolesCache.put(serialNumber[0], i); + + telnet.connect(LOCALHOST, Integer.parseInt(port)); + InputStream in = telnet.getInputStream(); + OutputStream out = telnet.getOutputStream(); + + String consoleName = CONSOLE_NAME + " - " + serialNumber[0]; + + if (i != null) + { + consoleName += " (" + i + ")"; + } + + telnetsCache.put(consoleName, telnet); + DeviceServicesPlugin.addConsoleKilledListener(listener); + DeviceServicesPlugin.redirectStreamsToConsole(in, out, consoleName); + } + catch (IOException e) + { + status = + new Status( + IStatus.ERROR, + DeviceServicesPlugin.PLUGIN_ID, + ServicesNLS.ERR_EmulatorConsoleHandler_CouldNotOpenTheConsoleShell, + e); + } + } + } + else + { + status = + new Status(IStatus.ERROR, DeviceServicesPlugin.PLUGIN_ID, + ServicesNLS.ERR_EmulatorConsoleHandler_CouldNotRetrieveTheEmulatorPort); + } + + return status; + } + + /* + * (non-Javadoc) + * @see org.eclipse.sequoyah.device.framework.model.handler.ServiceHandler#updatingService(org.eclipse.sequoyah.device.framework.model.IInstance, org.eclipse.core.runtime.IProgressMonitor) + */ + @Override + public IStatus updatingService(IInstance instance, IProgressMonitor monitor) + { + return Status.OK_STATUS; + } +} diff --git a/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/ddms/MonkeyServiceCommand.java b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/ddms/MonkeyServiceCommand.java new file mode 100644 index 0000000..ea44bd7 --- /dev/null +++ b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/ddms/MonkeyServiceCommand.java @@ -0,0 +1,52 @@ +/*
+ * Copyright (C) 2012 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.motorola.studio.android.devices.services.ddms;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.sequoyah.device.common.utilities.exception.SequoyahException;
+import org.eclipse.sequoyah.device.framework.model.IInstance;
+
+import com.motorola.studio.android.devices.services.DeviceServicesPlugin;
+import com.motorola.studio.android.emulator.core.model.IAndroidEmulatorInstance;
+import com.motorola.studio.android.emulator.ui.view.AbstractAndroidView;
+
+/**
+ * The default handler for Test events with Monkey command.
+ */
+public class MonkeyServiceCommand extends AbstractHandler implements IHandler
+{
+
+ public Object execute(ExecutionEvent event) throws ExecutionException
+ {
+ IAndroidEmulatorInstance instance = AbstractAndroidView.getActiveInstance();
+ if (instance instanceof IInstance)
+ {
+ try
+ {
+ DeviceServicesPlugin.getMonkeyServiceHandler().run((IInstance) instance);
+ }
+ catch (SequoyahException e)
+ {
+ //do nothing
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/ddms/MonkeyServiceHandler.java b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/ddms/MonkeyServiceHandler.java new file mode 100644 index 0000000..f08c89d --- /dev/null +++ b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/ddms/MonkeyServiceHandler.java @@ -0,0 +1,71 @@ +/*
+ * Copyright (C) 2012 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.motorola.studio.android.devices.services.ddms;
+
+import java.util.Map;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.sequoyah.device.framework.model.IInstance;
+import org.eclipse.sequoyah.device.framework.model.handler.IServiceHandler;
+import org.eclipse.sequoyah.device.framework.model.handler.ServiceHandler;
+
+import com.motorola.studio.android.adt.DDMSUtils;
+import com.motorola.studio.android.adt.ISerialNumbered;
+import com.motorola.studio.android.devices.services.i18n.ServicesNLS;
+
+/**
+ * The default handler for Test events with Monkey service.
+ */
+public class MonkeyServiceHandler extends ServiceHandler
+{
+ @Override
+ public IServiceHandler newInstance()
+ {
+ return new MonkeyServiceHandler();
+ }
+
+ @Override
+ public IStatus runService(IInstance instance, Map<Object, Object> arg1, IProgressMonitor arg2)
+ {
+ if (instance instanceof ISerialNumbered)
+ {
+ final String serialNumber = ((ISerialNumbered) instance).getSerialNumber();
+ final String deviceName = instance.getName();
+ Job job = new Job(ServicesNLS.JOB_Name_Monkey)
+ {
+ @Override
+ protected IStatus run(IProgressMonitor monitor)
+ {
+ DDMSUtils.runMonkey(serialNumber, deviceName);
+ return Status.OK_STATUS;
+ }
+
+ };
+ job.schedule();
+ }
+ return Status.OK_STATUS;
+ }
+
+ @Override
+ public IStatus updatingService(IInstance arg0, IProgressMonitor arg1)
+ {
+ return Status.OK_STATUS;
+ }
+
+}
diff --git a/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/ddms/ScreenshotServiceCommand.java b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/ddms/ScreenshotServiceCommand.java new file mode 100644 index 0000000..e72f176 --- /dev/null +++ b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/ddms/ScreenshotServiceCommand.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2012 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.motorola.studio.android.devices.services.ddms; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.IHandler; +import org.eclipse.sequoyah.device.common.utilities.exception.SequoyahException; +import org.eclipse.sequoyah.device.framework.model.IInstance; + +import com.motorola.studio.android.devices.services.DeviceServicesPlugin; +import com.motorola.studio.android.emulator.core.model.IAndroidEmulatorInstance; +import com.motorola.studio.android.emulator.ui.view.AbstractAndroidView; + +public class ScreenshotServiceCommand extends AbstractHandler implements IHandler +{ + + public Object execute(ExecutionEvent event) throws ExecutionException + { + IAndroidEmulatorInstance instance = AbstractAndroidView.getActiveInstance(); + if (instance instanceof IInstance) + { + try + { + DeviceServicesPlugin.getScreenshotServiceHandler().run((IInstance) instance); + } + catch (SequoyahException e) + { + //do nothing + } + } + return null; + } + +} diff --git a/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/ddms/ScreenshotServiceHandler.java b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/ddms/ScreenshotServiceHandler.java new file mode 100644 index 0000000..d70a6bd --- /dev/null +++ b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/ddms/ScreenshotServiceHandler.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2012 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.motorola.studio.android.devices.services.ddms; + +import java.util.Map; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.sequoyah.device.framework.model.IInstance; +import org.eclipse.sequoyah.device.framework.model.handler.IServiceHandler; +import org.eclipse.sequoyah.device.framework.model.handler.ServiceHandler; + +import com.motorola.studio.android.adt.DDMSUtils; +import com.motorola.studio.android.adt.ISerialNumbered; + +public class ScreenshotServiceHandler extends ServiceHandler +{ + @Override + public IServiceHandler newInstance() + { + return new ScreenshotServiceHandler(); + } + + @Override + public IStatus runService(IInstance instance, Map<Object, Object> arg1, IProgressMonitor arg2) + { + if (instance instanceof ISerialNumbered) + { + final String serialNumber = ((ISerialNumbered) instance).getSerialNumber(); + Job job = new Job("Screenshot") + { + @Override + protected IStatus run(IProgressMonitor monitor) + { + DDMSUtils.takeScreenshot(serialNumber); + return Status.OK_STATUS; + } + + }; + job.schedule(); + } + return Status.OK_STATUS; + } + + @Override + public IStatus updatingService(IInstance arg0, IProgressMonitor arg1) + { + return Status.OK_STATUS; + } + +} diff --git a/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/deploy/DeployServiceCommand.java b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/deploy/DeployServiceCommand.java new file mode 100644 index 0000000..f41c6e1 --- /dev/null +++ b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/deploy/DeployServiceCommand.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2012 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.motorola.studio.android.devices.services.deploy; + +import java.util.Arrays; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.sequoyah.device.common.utilities.exception.SequoyahException; +import org.eclipse.sequoyah.device.framework.manager.ServiceManager; +import org.eclipse.sequoyah.device.framework.model.IInstance; + +import com.motorola.studio.android.devices.services.DeviceServicesPlugin; +import com.motorola.studio.android.emulator.core.model.IAndroidEmulatorInstance; +import com.motorola.studio.android.emulator.ui.view.AbstractAndroidView; + +public class DeployServiceCommand extends AbstractHandler +{ + + public Object execute(ExecutionEvent event) throws ExecutionException + { + IAndroidEmulatorInstance emulatorInstance = AbstractAndroidView.getActiveInstance(); + if (emulatorInstance instanceof IInstance) + { + try + { + IInstance instance = (IInstance) emulatorInstance; + + ServiceManager.runServices(Arrays.asList(instance), + DeviceServicesPlugin.DEPLOY_SERVICE_ID); + } + catch (SequoyahException e) + { + //do nothing + } + } + return null; + } + +} diff --git a/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/deploy/DeployServiceHandler.java b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/deploy/DeployServiceHandler.java new file mode 100644 index 0000000..edb38c6 --- /dev/null +++ b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/deploy/DeployServiceHandler.java @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2012 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.motorola.studio.android.devices.services.deploy; + +import java.util.List; +import java.util.Map; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.sequoyah.device.framework.model.IInstance; +import org.eclipse.sequoyah.device.framework.model.handler.IServiceHandler; +import org.eclipse.sequoyah.device.framework.model.handler.ServiceHandler; + +import com.motorola.studio.android.adt.DDMSUtils; +import com.motorola.studio.android.adt.ISerialNumbered; +import com.motorola.studio.android.adt.InstallPackageBean; +import com.motorola.studio.android.common.log.StudioLogger; +import com.motorola.studio.android.devices.services.i18n.ServicesNLS; + +/** + * DESCRIPTION: + * This class plugs the deploy procedure to a TmL service + * + * RESPONSIBILITY: + * Implements the actions that will be triggered when + * user chose to Install a Android Application on an + * emulator instance. + * + * COLABORATORS: + * None. + * + * USAGE: + * This class is intended to be used by Eclipse only + * */ +public class DeployServiceHandler extends ServiceHandler +{ + protected InstallPackageBean installBean = null; + + /* + * (non-Javadoc) + * @see org.eclipse.sequoyah.device.framework.model.handler.ServiceHandler#newInstance() + */ + @Override + public IServiceHandler newInstance() + { + return new DeployServiceHandler(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.sequoyah.device.framework.model.handler.ServiceHandler#runService(org.eclipse.sequoyah.device.framework.model.IInstance, java.util.Map, org.eclipse.core.runtime.IProgressMonitor) + */ + @Override + public IStatus runService(IInstance instance, Map<Object, Object> arguments, + IProgressMonitor monitor) + { + if (instance instanceof ISerialNumbered) + { + final String serialNumber = ((ISerialNumbered) instance).getSerialNumber(); + Job j = new Job(ServicesNLS.JOB_Name_Install_Application + " (" + serialNumber + ")") + { + + @Override + protected IStatus run(IProgressMonitor monitor) + { + return DDMSUtils.installPackage(serialNumber, installBean); + } + }; + j.schedule(); + } + + return Status.OK_STATUS; + } + + /* + * (non-Javadoc) + * @see org.eclipse.sequoyah.device.framework.model.handler.ServiceHandler#updatingService(org.eclipse.sequoyah.device.framework.model.IInstance, org.eclipse.core.runtime.IProgressMonitor) + */ + @Override + public IStatus updatingService(IInstance instance, IProgressMonitor monitor) + { + StudioLogger.info("Updating reset service"); + return Status.OK_STATUS; + } + + @Override + public IStatus singleInit(List<IInstance> instances) + { + + this.installBean = DDMSUtils.installPackageWizard(); + + return super.singleInit(instances); + } +} diff --git a/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/deploy/EmulatorTester.java b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/deploy/EmulatorTester.java new file mode 100644 index 0000000..b710ee7 --- /dev/null +++ b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/deploy/EmulatorTester.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2012 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.motorola.studio.android.devices.services.deploy; + +import org.eclipse.core.expressions.PropertyTester; + +import com.motorola.studio.android.emulator.ui.view.AbstractAndroidView; + +public class EmulatorTester extends PropertyTester +{ + + public boolean test(Object receiver, String property, Object[] args, Object expectedValue) + { + return AbstractAndroidView.getActiveInstance() != null; + } + +} diff --git a/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/deploy/UninstallAppServiceCommand.java b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/deploy/UninstallAppServiceCommand.java new file mode 100644 index 0000000..9a6f62a --- /dev/null +++ b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/deploy/UninstallAppServiceCommand.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2012 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.motorola.studio.android.devices.services.deploy; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.sequoyah.device.common.utilities.exception.SequoyahException; +import org.eclipse.sequoyah.device.framework.model.IInstance; + +import com.motorola.studio.android.devices.services.DeviceServicesPlugin; +import com.motorola.studio.android.emulator.core.model.IAndroidEmulatorInstance; +import com.motorola.studio.android.emulator.ui.view.AbstractAndroidView; + +public class UninstallAppServiceCommand extends AbstractHandler +{ + + public Object execute(ExecutionEvent event) throws ExecutionException + { + IAndroidEmulatorInstance instance = AbstractAndroidView.getActiveInstance(); + if (instance instanceof IInstance) + { + try + { + DeviceServicesPlugin.getUninstallAppServiceHandler().run((IInstance) instance); + } + catch (SequoyahException e) + { + //do nothing + } + } + return null; + } + +} diff --git a/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/deploy/UninstallAppServiceHandler.java b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/deploy/UninstallAppServiceHandler.java new file mode 100644 index 0000000..8075d29 --- /dev/null +++ b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/deploy/UninstallAppServiceHandler.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2012 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.motorola.studio.android.devices.services.deploy; + +import java.util.Map; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.sequoyah.device.framework.model.IInstance; +import org.eclipse.sequoyah.device.framework.model.handler.IServiceHandler; +import org.eclipse.sequoyah.device.framework.model.handler.ServiceHandler; + +import com.motorola.studio.android.adt.DDMSUtils; +import com.motorola.studio.android.adt.ISerialNumbered; +import com.motorola.studio.android.common.log.StudioLogger; +import com.motorola.studio.android.devices.services.i18n.ServicesNLS; + +/** + * DESCRIPTION: + * This class plugs the deploy procedure to a TmL service + * + * RESPONSIBILITY: + * Implements the actions that will be triggered when + * user chose to Install a Android Application on an + * emulator instance. + * + * COLABORATORS: + * None. + * + * USAGE: + * This class is intended to be used by Eclipse only + * */ +public class UninstallAppServiceHandler extends ServiceHandler +{ + /* + * (non-Javadoc) + * @see org.eclipse.sequoyah.device.framework.model.handler.ServiceHandler#newInstance() + */ + @Override + public IServiceHandler newInstance() + { + return new UninstallAppServiceHandler(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.sequoyah.device.framework.model.handler.ServiceHandler#runService(org.eclipse.sequoyah.device.framework.model.IInstance, java.util.Map, org.eclipse.core.runtime.IProgressMonitor) + */ + @Override + public IStatus runService(IInstance instance, Map<Object, Object> arguments, + IProgressMonitor monitor) + { + if (instance instanceof ISerialNumbered) + { + final String serialNumber = ((ISerialNumbered) instance).getSerialNumber(); + Job j = new Job(ServicesNLS.JOB_Name_Uninstall_Application) + { + + @Override + protected IStatus run(IProgressMonitor monitor) + { + return DDMSUtils.uninstallPackage(serialNumber); + } + }; + j.schedule(); + } + + return Status.OK_STATUS; + } + + /* + * (non-Javadoc) + * @see org.eclipse.sequoyah.device.framework.model.handler.ServiceHandler#updatingService(org.eclipse.sequoyah.device.framework.model.IInstance, org.eclipse.core.runtime.IProgressMonitor) + */ + @Override + public IStatus updatingService(IInstance instance, IProgressMonitor monitor) + { + StudioLogger.info("Updating reset service"); + return Status.OK_STATUS; + } +} diff --git a/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/i18n/ServicesNLS.java b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/i18n/ServicesNLS.java new file mode 100644 index 0000000..9a96fe4 --- /dev/null +++ b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/i18n/ServicesNLS.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2012 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.motorola.studio.android.devices.services.i18n; + +import org.eclipse.osgi.util.NLS; + +/** + * NLS class for the plugin com.motorola.studio.android.device.service.console + */ +public class ServicesNLS extends NLS +{ + static + { + NLS.initializeMessages("com.motorola.studio.android.devices.services.i18n.servicesNLS", + ServicesNLS.class); + } + + public static String ADBShellHandler_WaitingDeviceToLoad; + + /* + * General Strings area + */ + public static String GEN_Warning; + + /* + * Error Strings area + */ + public static String ERR_ADBShellHandler_CouldNotExecuteTheAdbShell; + + public static String ERR_ADBShellHandler_MissingAdbShell; + + public static String ERR_ADBShellHandler_AndroidSdkIsNotConfigured; + + public static String ERR_EmulatorConsoleHandler_CouldNotOpenTheConsoleShell; + + public static String ERR_EmulatorConsoleHandler_CouldNotRetrieveTheEmulatorPort; + + /* + * Warning Strings area + */ + public static String WARN_EmulatorConsoleHandler_CouldNotCloseTheConsoleConnection; + + /* + * Deploy service area + */ + public static String JOB_Name_Install_Application; + + public static String JOB_Name_Uninstall_Application; + + /* + * Languade service area + */ + + public static String UI_Language; + + public static String UI_Country; + + public static String UI_Wizard_Title; + + public static String UI_Wizard_Page_Locale_Title; + + public static String UI_Wizard_Page_Locale_Description; + + /* + * Monkey service area + */ + public static String JOB_Name_Monkey; +} diff --git a/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/i18n/servicesNLS.properties b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/i18n/servicesNLS.properties new file mode 100644 index 0000000..18ac12f --- /dev/null +++ b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/i18n/servicesNLS.properties @@ -0,0 +1,30 @@ +ADBShellHandler_WaitingDeviceToLoad=Waiting for device to load... +GEN_Warning=Warning + +ERR_ADBShellHandler_CouldNotExecuteTheAdbShell=Could not execute the adb shell. + +ERR_ADBShellHandler_MissingAdbShell=The adb executable is not in the Android SDK path. + +ERR_ADBShellHandler_AndroidSdkIsNotConfigured=The Android SDK is not configured. + +ERR_EmulatorConsoleHandler_CouldNotOpenTheConsoleShell=Could not open the console shell. + +ERR_EmulatorConsoleHandler_CouldNotRetrieveTheEmulatorPort=Could not retrieve the emulator port. + +WARN_EmulatorConsoleHandler_CouldNotCloseTheConsoleConnection=Could not close the Emulator Console connection. This will not keep you from working with MOTODEV Studio for Android, and will be fixed when you close MOTODEV Studio. + +JOB_Name_Install_Application=Install Application + +JOB_Name_Uninstall_Application=Uninstall Application + +JOB_Name_Monkey=Test events with Monkey + +UI_Language=Language + +UI_Country=Country + +UI_Wizard_Title=Language + +UI_Wizard_Page_Locale_Title=Emulator Language + +UI_Wizard_Page_Locale_Description=Change the device's language configuration. This will only take effect after you manually restart the emulator. diff --git a/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/lang/LangServiceCommand.java b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/lang/LangServiceCommand.java new file mode 100644 index 0000000..5504f0c --- /dev/null +++ b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/lang/LangServiceCommand.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2012 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.motorola.studio.android.devices.services.lang; + +import java.util.Arrays; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.sequoyah.device.common.utilities.exception.SequoyahException; +import org.eclipse.sequoyah.device.framework.manager.ServiceManager; +import org.eclipse.sequoyah.device.framework.model.IInstance; + +import com.motorola.studio.android.devices.services.DeviceServicesPlugin; +import com.motorola.studio.android.emulator.core.model.IAndroidEmulatorInstance; +import com.motorola.studio.android.emulator.ui.view.AbstractAndroidView; + +/** + * Open Change language wizard + */ +public class LangServiceCommand extends AbstractHandler +{ + + /* (non-Javadoc) + * @see org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands.ExecutionEvent) + */ + public Object execute(ExecutionEvent event) throws ExecutionException + { + IAndroidEmulatorInstance emulatorInstance = AbstractAndroidView.getActiveInstance(); + if (emulatorInstance instanceof IInstance) + { + try + { + IInstance instance = (IInstance) emulatorInstance; + + ServiceManager.runServices(Arrays.asList(instance), + DeviceServicesPlugin.ANDROID_LANG_SERVICE_ID); + } + catch (SequoyahException e) + { + //do nothing + } + } + return null; + } +} diff --git a/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/lang/LangServiceHandler.java b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/lang/LangServiceHandler.java new file mode 100644 index 0000000..c5b60b1 --- /dev/null +++ b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/lang/LangServiceHandler.java @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2012 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.motorola.studio.android.devices.services.lang; + +import java.util.List; +import java.util.Map; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.sequoyah.device.framework.model.IInstance; +import org.eclipse.sequoyah.device.framework.model.handler.IServiceHandler; +import org.eclipse.sequoyah.device.framework.model.handler.ServiceHandler; +import org.eclipse.ui.PlatformUI; + +import com.motorola.studio.android.adt.DDMSUtils; +import com.motorola.studio.android.adt.ISerialNumbered; +import com.motorola.studio.android.common.log.StudioLogger; +import com.motorola.studio.android.devices.services.DeviceServicesPlugin; +import com.motorola.studio.android.devices.services.lang.model.LangWizard; + +/** + * This class plugs the change language procedure to a TmL service + */ +public class LangServiceHandler extends ServiceHandler +{ + private String languageID; + + private String countryID; + + /* + * (non-Javadoc) + * + * @seeorg.eclipse.sequoyah.device.framework.model.handler.ServiceHandler# + * newInstance() + */ + @Override + public IServiceHandler newInstance() + { + return new LangServiceHandler(); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.sequoyah.device.framework.model.handler.ServiceHandler#runService + * (org.eclipse.sequoyah.device.framework.model.IInstance, java.util.Map, + * org.eclipse.core.runtime.IProgressMonitor) + */ + @Override + public IStatus runService(IInstance instance, Map<Object, Object> arguments, + IProgressMonitor monitor) + { + IStatus status = Status.OK_STATUS; + + final String serialNumber = ((ISerialNumbered) instance).getSerialNumber(); + + DDMSUtils.changeLanguage(serialNumber, languageID, countryID); + + // Collecting usage data for statistical purpose + try + { + StudioLogger.collectUsageData(StudioLogger.WHAT_EMULATOR_LANGUAGE, + StudioLogger.KIND_EMULATOR, languageID, DeviceServicesPlugin.PLUGIN_ID, + DeviceServicesPlugin.getDefault().getBundle().getVersion().toString()); + } + catch (Throwable e) + { + //Do nothing, but error on the log should never prevent app from working + } + + return status; + } + + /* + * (non-Javadoc) + * + * @seeorg.eclipse.sequoyah.device.framework.model.handler.ServiceHandler# + * updatingService(org.eclipse.sequoyah.device.framework.model.IInstance, + * org.eclipse.core.runtime.IProgressMonitor) + */ + @Override + public IStatus updatingService(IInstance instance, IProgressMonitor monitor) + { + StudioLogger.info("Updating change language service"); + return Status.OK_STATUS; + } + + @Override + public IStatus singleInit(final List<IInstance> instances) + { + PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() + { + public void run() + { + try + { + LangWizard wizard = new LangWizard(); + WizardDialog dialog = + new WizardDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow() + .getShell(), wizard); + dialog.setPageSize(250, 75); + + int ret = dialog.open(); + + if (ret == Dialog.OK) + { + languageID = wizard.getlanguageId(); + countryID = wizard.getcountryId(); + } + else + { + languageID = null; + countryID = null; + } + + } + catch (Exception e) + { + StudioLogger.error("Change Language TmL Service: could not open UI"); + } + } + }); + + return super.singleInit(instances); + } +} diff --git a/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/lang/model/Country.java b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/lang/model/Country.java new file mode 100644 index 0000000..f2bcb93 --- /dev/null +++ b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/lang/model/Country.java @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2012 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.motorola.studio.android.devices.services.lang.model; + +import java.io.InputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +import com.motorola.studio.android.common.log.StudioLogger; +import com.motorola.studio.android.devices.services.DeviceServicesPlugin; + +/** + * Country representation + * + * The list of countries has been downloaded from: + * http://www.iso.org/iso/country_codes/iso_3166_code_lists.htm + */ +public class Country +{ + + private static final String FILE_PATH = "resources/iso_3166-1_list_en.xml"; + + private static final String COUNTRY_NODE = "ISO_3166-1_Entry"; + + private static final String COUNTRY_NAME = "ISO_3166-1_Country_name"; + + private static final String COUNTRY_ID = "ISO_3166-1_Alpha-2_Code_element"; + + private static List<Country> countryList = null; + + private static Map<String, Country> countryMap = null; + + private String name; + + private String id; + + /** + * Get the countries list + * + * @return the countries list + */ + public static List<Country> getCountryList() + { + if (countryList == null) + { + loadCountries(); + } + return countryList; + } + + /* + * Load countries from XML file + */ + private static void loadCountries() + { + countryList = new ArrayList<Country>(); + countryMap = new HashMap<String, Country>(); + + URL countriesURL = DeviceServicesPlugin.getDefault().getBundle().getResource(FILE_PATH); + + try + { + + InputStream countriesIS = countriesURL.openStream(); + + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + Document document = builder.parse(countriesIS); + + NodeList list = document.getDocumentElement().getElementsByTagName(COUNTRY_NODE); + + for (int i = 0; i < list.getLength(); i++) + { + + Element countryNode = (Element) list.item(i); + + String name = + countryNode.getElementsByTagName(COUNTRY_NAME).item(0).getChildNodes() + .item(0).getNodeValue(); + String ID = + countryNode.getElementsByTagName(COUNTRY_ID).item(0).getChildNodes() + .item(0).getNodeValue(); + + if (((ID != null) && (!ID.equals(""))) && ((name != null) && (!name.equals("")))) + { + Country country = new Country(name, ID); + countryList.add(country); + countryMap.put(name, country); + } + } + + } + catch (Exception e) + { + StudioLogger.error("Change Language TmL Service: could not load countries list"); + } + + } + + /** + * Get country ID from country name + * + * @param countryName country name + * @return country ID + */ + public static String getIdFromName(String countryName) + { + String id = null; + Country country = countryMap.get(countryName); + if (country != null) + { + id = country.getId(); + } + return id; + } + + /** + * Constructor + * + * @param name country name + * @param id country name + */ + public Country(String name, String id) + { + super(); + this.name = name; + this.id = id; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public String getId() + { + return id; + } + + public void setId(String id) + { + this.id = id; + } + +} diff --git a/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/lang/model/LangWizard.java b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/lang/model/LangWizard.java new file mode 100644 index 0000000..86266d6 --- /dev/null +++ b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/lang/model/LangWizard.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2012 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.motorola.studio.android.devices.services.lang.model; + +import org.eclipse.jface.wizard.Wizard; + +import com.motorola.studio.android.devices.services.DeviceServicesPlugin; +import com.motorola.studio.android.devices.services.i18n.ServicesNLS; + +/** + * Change Language Wizard used to change the device language configuration + */ +public class LangWizard extends Wizard +{ + + private final String WIZARD_IMAGE_PATH = "resources/flag.png"; + + private LangWizardPage page; + + private final String[] currentLangAndCountry = null; + + private String languageID; + + private String countryID; + + public LangWizard() + { + this.setWindowTitle(ServicesNLS.UI_Wizard_Title); + super.setDefaultPageImageDescriptor(DeviceServicesPlugin + .getImageDescriptor(WIZARD_IMAGE_PATH)); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.wizard.Wizard#addPages() + */ + @Override + public void addPages() + { + page = new LangWizardPage(currentLangAndCountry); + super.addPage(page); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.wizard.Wizard#canFinish() + */ + @Override + public boolean canFinish() + { + return page.isPageComplete(); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.wizard.Wizard#performFinish() + */ + @Override + public boolean performFinish() + { + languageID = Language.getIdFromName(page.getLanguage()); + countryID = Country.getIdFromName(page.getCountry()); + + return true; + } + + public String getlanguageId() + { + return languageID; + } + + public String getcountryId() + { + return countryID; + } +} diff --git a/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/lang/model/LangWizardPage.java b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/lang/model/LangWizardPage.java new file mode 100644 index 0000000..6ab2296 --- /dev/null +++ b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/lang/model/LangWizardPage.java @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2012 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.motorola.studio.android.devices.services.lang.model; + +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.ui.PlatformUI; + +import com.motorola.studio.android.devices.services.DeviceServicesPlugin; +import com.motorola.studio.android.devices.services.i18n.ServicesNLS; + +/** + * Page where the user can choose the language the user wants + * to apply to the emulator + */ +public class LangWizardPage extends WizardPage +{ + + // main composite + LocationComposite locationComposite = null; + + private String[] currentLangAndCountry = null; + + /** + * Constructor + */ + public LangWizardPage() + { + this(null); + } + + /** + * Constructor + */ + public LangWizardPage(String[] currentLangAndCountry) + { + super("langWizardPage"); + this.currentLangAndCountry = currentLangAndCountry; + setTitle(ServicesNLS.UI_Wizard_Page_Locale_Title); + setDescription(ServicesNLS.UI_Wizard_Page_Locale_Description); + setPageComplete(false); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite) + */ + public void createControl(Composite parent) + { + + // Set Help ID + PlatformUI.getWorkbench().getHelpSystem() + .setHelp(parent, DeviceServicesPlugin.LANG_PAGE_CONTEXT_HELP_ID); + + // Define layout + GridLayout mainLayout = new GridLayout(1, false); + mainLayout.marginTop = 0; + mainLayout.marginWidth = 0; + mainLayout.marginHeight = 0; + + if (currentLangAndCountry != null) + { + locationComposite = + new LocationComposite(parent, currentLangAndCountry[0], + currentLangAndCountry[1]); + } + else + { + locationComposite = new LocationComposite(parent); + } + + locationComposite.addListener(LocationComposite.LOCATION_CHANGE, new Listener() + { + public void handleEvent(Event arg0) + { + updatePageComplete(); + } + }); + + locationComposite.setLayoutData(mainLayout); + setControl(locationComposite); + } + + /** + * Check if the "Next" button can be enabled by checking if the user has filled all the fields + */ + private void updatePageComplete() + { + setPageComplete(false); + String language = Language.getIdFromName(locationComposite.getLanguage()); + String country = Country.getIdFromName(locationComposite.getCountry()); + if ((currentLangAndCountry == null) + || (!currentLangAndCountry[0].equals(language) || !currentLangAndCountry[1] + .equals(country))) + { + setPageComplete(true); + } + } + + /** + * Get the selected language + * + * @return selected language name + */ + public String getLanguage() + { + return locationComposite.getLanguage(); + } + + /** + * Get the selected country + * + * @return selected country name + */ + public String getCountry() + { + return locationComposite.getCountry(); + } + +} diff --git a/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/lang/model/Language.java b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/lang/model/Language.java new file mode 100644 index 0000000..ed659ce --- /dev/null +++ b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/lang/model/Language.java @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2012 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.motorola.studio.android.devices.services.lang.model; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.runtime.FileLocator; + +import com.motorola.studio.android.common.log.StudioLogger; +import com.motorola.studio.android.devices.services.DeviceServicesPlugin; + +/** + * Language representation + * + * The list of languages has been downloaded from: + * http://www.loc.gov/standards/iso639-2/ascii_8bits.html + */ +public class Language +{ + + private static final String FILE_PATH = "resources/ISO-639-2_utf-8.txt"; + + private static List<Language> languageList = null; + + private static Map<String, Language> languageMap = null; + + private String name; + + private String id; + + /** + * Get the languages list + * + * @return the languages list + */ + public static List<Language> getLanguageList() + { + if (languageList == null) + { + loadLanguages(); + } + return languageList; + } + + /** + * Load languages from TXT file + */ + private static void loadLanguages() + { + languageList = new ArrayList<Language>(); + languageMap = new HashMap<String, Language>(); + + URL languagesURL = DeviceServicesPlugin.getDefault().getBundle().getResource(FILE_PATH); + + BufferedReader input = null; + try + { + + File file = new File(FileLocator.toFileURL(languagesURL).getPath()); + + input = new BufferedReader(new FileReader(file)); + + String line = null; + String[] lineParts = null; + String name = null; + String ID = null; + while ((line = input.readLine()) != null) + { + lineParts = line.split("\\|"); + ID = lineParts[2]; + name = lineParts[3]; + if (((ID != null) && (!ID.equals(""))) && ((name != null) && (!name.equals("")))) + { + Language language = new Language(name, ID); + languageList.add(language); + languageMap.put(name, language); + } + } + } + catch (Exception e) + { + StudioLogger.error("Change Language TmL Service: could not load languages list"); + } + finally + { + if (input != null) + { + try + { + input.close(); + } + catch (IOException e) + { + } + } + } + + } + + /** + * Get language ID from language name + * + * @param langName language name + * @return language ID + */ + public static String getIdFromName(String langName) + { + String id = null; + Language language = languageMap.get(langName); + if (language != null) + { + id = language.getId(); + } + return id; + } + + /** + * Constructs a new Language instance, based on the given name and id. + * @param name language name + * @param id language id + */ + public Language(String name, String id) + { + super(); + this.name = name; + this.id = id; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public String getId() + { + return id; + } + + public void setId(String id) + { + this.id = id; + } + +} diff --git a/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/lang/model/LocationComposite.java b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/lang/model/LocationComposite.java new file mode 100644 index 0000000..ae2a97b --- /dev/null +++ b/src/plugins/devices.services/src/com/motorola/studio/android/devices/services/lang/model/LocationComposite.java @@ -0,0 +1,321 @@ +/* + * Copyright (C) 2012 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.motorola.studio.android.devices.services.lang.model; + +import java.util.List; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; + +import com.motorola.studio.android.devices.services.i18n.ServicesNLS; + +/** + * Composite containing the current language in use and two combo boxes where + * the user can choose a language and country + */ +public class LocationComposite extends Composite +{ + // id for listeners + static final int LOCATION_CHANGE = 1234; + + // selected language + private String language = ""; + + // selected country + private String country = ""; + + // language combobox + private Combo comboLanguage = null; + + // country combobox + private Combo comboCountry = null; + + /** + * Constructor + * + * @param parent the parent composite + */ + public LocationComposite(Composite parent) + { + this(parent, null, null); + } + + /** + * Constructor + * + * @param parent the parent composite + * @param currentLanguageId the id of the current language in use by given emulator instance. + * @param currentCountryId the id of the current country in use by given emulator instance. + */ + public LocationComposite(Composite parent, String currentLanguageId, String currentCountryId) + { + super(parent, SWT.NONE); + + Label label; + GridLayout gridLayout = new GridLayout(); + gridLayout.numColumns = 2; + this.setLayout(gridLayout); + + /* + * Language label and combobox + */ + label = new Label(this, SWT.LEFT); + label.setText(ServicesNLS.UI_Language); + + comboLanguage = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY); + comboLanguage.addSelectionListener(new SelectionAdapter() + { + @Override + public void widgetSelected(SelectionEvent event) + { + language = comboLanguage.getText(); + notifyListeners(LOCATION_CHANGE, null); + } + }); + if ((currentLanguageId != null) && (!currentLanguageId.equals(""))) + { + fillComboBoxAndSelectCurrentLanguage(currentLanguageId); + } + else + { + comboLanguage.setItems(getLanguagesList()); + } + language = comboLanguage.getText(); + comboLanguage.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + comboLanguage.setVisibleItemCount(20); + + /* + * Country label and combobox + */ + label = new Label(this, SWT.LEFT); + label.setText(ServicesNLS.UI_Country); + + comboCountry = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY); + comboCountry.addSelectionListener(new SelectionAdapter() + { + @Override + public void widgetSelected(SelectionEvent event) + { + country = comboCountry.getText(); + notifyListeners(LOCATION_CHANGE, null); + } + }); + if ((currentCountryId != null) && (!currentCountryId.equals(""))) + { + fillComboBoxAndSelectCurrentCountry(currentCountryId); + } + else + { + comboCountry.setItems(getCountriesList()); + } + country = comboCountry.getText(); + comboCountry.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + comboCountry.setVisibleItemCount(20); + } + + /* + * Sets an array of languages in the language combo box and select that item which is + * the current in use by emulator instance. <p> + * + * There are some needed explanations here: <p> + * + * 1. The currentLanguageId parameter was obtained through an ADB shell command sent + * to emulator. The ID returned is a String similar to "pt", "en", "fr" for Portuguese, + * English and French respectively. For more details, please see: <br> + * com.motorola.studio.android.adt.DDMSUtils.getCurrentEmulatorLanguageAndCountry + * method. <p> + * + * 2. The currentLanguageId parameter is passed to getLanguagesList method in order to + * be returned an array of Strings holding all languages available and, at the + * length-plus-one position of this array, the number representing the index of + * array regarding the current language name in use by emulator. <p> + * + * 3. The language combo box is filled with all languages contained in langNamesAndIndex + * array. Then the number, held at last position of array, is passed as parameter to + * select() method of the combo box. Thus, the current language appears as selected + * when combo box is rendered. <p> + * + * @param currentLanguageId The ID of the current language in use by emulator + * instance. + */ + private void fillComboBoxAndSelectCurrentLanguage(String currentLanguageId) + { + String[] langNamesAndIndex = getLanguagesList(currentLanguageId); + int index = langNamesAndIndex.length - 1; + int currentLanguageIndex = Integer.parseInt(langNamesAndIndex[index]); + comboLanguage.setItems(langNamesAndIndex); + comboLanguage.remove(index); + comboLanguage.select(currentLanguageIndex); + } + + /* + * Sets an array of countries in the country combo box and select that item which is + * the current in use by emulator instance. <p> + * + * There are some needed explanations here: <p> + * + * 1. The currentCountryId parameter was obtained through an ADB shell command sent + * to emulator. The ID returned is a String similar to "it", "us", "ru" for Italy, + * USA and Russia respectively. For more details, please see: <br> + * com.motorola.studio.android.adt.DDMSUtils.getCurrentEmulatorLanguageAndCountry + * method. <p> + * + * 2. The currentCountryId parameter is passed to getCountriesList method in order to + * be returned an array of Strings holding all country available and, at the + * length-plus-one position of this array, the number representing the index of + * array regarding the current country name in use by emulator. <p> + * + * 3. The country combo box is filled with all countries contained in countryNamesAndIndex + * array. Then the number, held at last position of array, is passed as parameter to + * select() method of the combo box. Thus, the current country appears as selected + * when combo box is rendered. <p> + * + * @param currentCountryId The ID of the current country in use by emulator + * instance. + */ + private void fillComboBoxAndSelectCurrentCountry(String currentCountryId) + { + String[] countryNamesAndIndex = getCountriesList(currentCountryId); + int index = countryNamesAndIndex.length - 1; + int currentCountryIndex = Integer.parseInt(countryNamesAndIndex[index]); + comboCountry.setItems(countryNamesAndIndex); + comboCountry.remove(index); + comboCountry.select(currentCountryIndex); + } + + /* + * Get the list of languages to be used to populate the combobox + * + * @return the list of languages to be used to populate the combobox + */ + private String[] getLanguagesList() + { + List<Language> languageObjs = Language.getLanguageList(); + String[] languages = new String[languageObjs.size()]; + + int i = 0; + for (Language language : languageObjs) + { + languages[i] = language.getName(); + i++; + } + return languages; + } + + /* + * Get the list of languages to be used to populate the combo box. Also, + * returns the index of the current language at last position of the array. + * + * @param currentlanguageId + * @return An array of Strings containing the list of languages and the + * current language index. + */ + private String[] getLanguagesList(String currentlanguageId) + { + List<Language> languageObjs = Language.getLanguageList(); + int size = languageObjs.size(); + String[] langNamesAndIndex = new String[size + 1]; + String languageIndex = null; + int i = 0; + for (Language language : languageObjs) + { + String name = language.getName(); + String id = language.getId(); + if (id.equalsIgnoreCase(currentlanguageId)) + { + languageIndex = String.valueOf(i); + langNamesAndIndex[size] = languageIndex; + } + langNamesAndIndex[i] = name; + i++; + } + return langNamesAndIndex; + } + + /* + * Get the list of countries to be used to populate the combobox + * + * @return the list of countries to be used to populate the combobox + */ + private String[] getCountriesList() + { + List<Country> countryObjs = Country.getCountryList(); + String[] countries = new String[countryObjs.size()]; + int i = 0; + for (Country country : countryObjs) + { + countries[i] = country.getName(); + i++; + } + return countries; + } + + /* + * Get the list of countries to be used to populate the combo box. Also, + * returns the index of the current country at last position of the array. + * + * @param currentCountryId + * @return An array of Strings containing the list of countries and the + * current country index. + */ + private String[] getCountriesList(String currentCountryId) + { + List<Country> countryObjs = Country.getCountryList(); + int size = countryObjs.size(); + String[] countryNamesAndIndex = new String[size + 1]; + String countryIndex = null; + int i = 0; + for (Country country : countryObjs) + { + String name = country.getName(); + String id = country.getId(); + if (id.equalsIgnoreCase(currentCountryId)) + { + countryIndex = String.valueOf(i); + countryNamesAndIndex[size] = countryIndex; + } + countryNamesAndIndex[i] = name; + i++; + } + return countryNamesAndIndex; + } + + /** + * Get the selected language + * + * @return selected language name + */ + public String getLanguage() + { + return language; + } + + /** + * Get the selected country + * + * @return selected country name + */ + public String getCountry() + { + return country; + } +} |