| /* |
| * 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); |
| } |
| } |
| }; |
| |
| } |