| /* |
| * Copyright (C) 2009 The Android Open Source Project |
| * |
| * Licensed under the Eclipse Public License, Version 1.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.eclipse.org/org/documents/epl-v10.php |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.android.ide.eclipse.adt.internal.launch; |
| |
| import com.android.ddmlib.IDevice; |
| import com.android.ddmlib.MultiLineReceiver; |
| import com.android.ide.eclipse.adt.AdtPlugin; |
| |
| import java.util.ArrayList; |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| |
| |
| /** |
| * Output receiver for am process (Activity Manager) |
| * |
| * Monitors adb output for am errors, and retries launch as appropriate. |
| */ |
| public class AMReceiver extends MultiLineReceiver { |
| |
| private static final int MAX_ATTEMPT_COUNT = 5; |
| private static final Pattern sAmErrorType = Pattern.compile("Error type (\\d+)"); //$NON-NLS-1$ |
| |
| private final DelayedLaunchInfo mLaunchInfo; |
| private final IDevice mDevice; |
| private final ILaunchController mLaunchController; |
| |
| /** |
| * Basic constructor. |
| * |
| * @param launchInfo the {@link DelayedLaunchInfo} associated with the am process. |
| * @param device the Android device on which the launch is done. |
| * @param launchController the {@link ILaunchController} that is managing the launch |
| */ |
| public AMReceiver(DelayedLaunchInfo launchInfo, IDevice device, |
| ILaunchController launchController) { |
| mLaunchInfo = launchInfo; |
| mDevice = device; |
| mLaunchController = launchController; |
| } |
| |
| /** |
| * Monitors the am process for error messages. If an error occurs, will reattempt launch up to |
| * <code>MAX_ATTEMPT_COUNT</code> times. |
| * |
| * @param lines a portion of the am output |
| * |
| * @see MultiLineReceiver#processNewLines(String[]) |
| */ |
| @Override |
| public void processNewLines(String[] lines) { |
| // first we check if one starts with error |
| ArrayList<String> array = new ArrayList<String>(); |
| boolean error = false; |
| boolean warning = false; |
| for (String s : lines) { |
| // ignore empty lines. |
| if (s.length() == 0) { |
| continue; |
| } |
| |
| // check for errors that output an error type, if the attempt count is still |
| // valid. If not the whole text will be output in the console |
| if (mLaunchInfo.getAttemptCount() < MAX_ATTEMPT_COUNT && |
| mLaunchInfo.isCancelled() == false) { |
| Matcher m = sAmErrorType.matcher(s); |
| if (m.matches()) { |
| // get the error type |
| int type = Integer.parseInt(m.group(1)); |
| |
| final int waitTime = 3; |
| String msg; |
| |
| switch (type) { |
| case 1: |
| /* Intended fall through */ |
| case 2: |
| msg = String.format( |
| "Device not ready. Waiting %1$d seconds before next attempt.", |
| waitTime); |
| break; |
| case 3: |
| msg = String.format( |
| "New package not yet registered with the system. Waiting %1$d seconds before next attempt.", |
| waitTime); |
| break; |
| default: |
| msg = String.format( |
| "Device not ready (%2$d). Waiting %1$d seconds before next attempt.", |
| waitTime, type); |
| break; |
| |
| } |
| |
| AdtPlugin.printToConsole(mLaunchInfo.getProject(), msg); |
| |
| // launch another thread, that waits a bit and attempts another launch |
| new Thread("Delayed Launch attempt") { |
| @Override |
| public void run() { |
| try { |
| sleep(waitTime * 1000); |
| } catch (InterruptedException e) { |
| // ignore |
| } |
| |
| mLaunchController.launchApp(mLaunchInfo, mDevice); |
| } |
| }.start(); |
| |
| // no need to parse the rest |
| return; |
| } |
| } |
| |
| // check for error if needed |
| if (error == false && s.startsWith("Error:")) { //$NON-NLS-1$ |
| error = true; |
| } |
| if (warning == false && s.startsWith("Warning:")) { //$NON-NLS-1$ |
| warning = true; |
| } |
| |
| // add the line to the list |
| array.add("ActivityManager: " + s); //$NON-NLS-1$ |
| } |
| |
| // then we display them in the console |
| if (warning || error) { |
| AdtPlugin.printErrorToConsole(mLaunchInfo.getProject(), array.toArray()); |
| } else { |
| AdtPlugin.printToConsole(mLaunchInfo.getProject(), array.toArray()); |
| } |
| |
| // if error then we cancel the launch, and remove the delayed info |
| if (error) { |
| mLaunchController.stopLaunch(mLaunchInfo); |
| } |
| } |
| |
| /** |
| * Returns true if launch has been cancelled |
| */ |
| @Override |
| public boolean isCancelled() { |
| return mLaunchInfo.isCancelled(); |
| } |
| } |