diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AMReceiver.java')
-rw-r--r-- | eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AMReceiver.java | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AMReceiver.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AMReceiver.java new file mode 100644 index 000000000..ea61945a2 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AMReceiver.java @@ -0,0 +1,161 @@ +/* + * 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(); + } +} |