Cts框架解析(9)-IDeviceRecovery

当设备处于offline状态时,cts框架就要调用IDeviceRecovery接口类去做相应的恢复工作。

接口

/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.tradefed.device;

/**
 * Interface for recovering a device that has gone offline.
 */
public interface IDeviceRecovery {

    /**
     * Attempt to recover the given device that can no longer be communicated with.
     * <p/>
     * Method should block and only return when device is in requested state.
     *
     * @param monitor the {@link IDeviceStateMonitor} to use.
     * @param recoverUntilOnline if true, method should return as soon as device is online on adb.
     *            If false, method should block until device is fully available for testing (ie
     *            {@link IDeviceStateMonitor#waitForDeviceAvailable()} succeeds.
     * @throws DeviceNotAvailableException if device could not be recovered
     */
    public void recoverDevice(IDeviceStateMonitor monitor, boolean recoverUntilOnline)
            throws DeviceNotAvailableException;

    /**
     * Attempt to recover the given unresponsive device in recovery mode.
     *
     * @param monitor the {@link IDeviceStateMonitor} to use.
     * @throws DeviceNotAvailableException if device could not be recovered
     */
    public void recoverDeviceRecovery(IDeviceStateMonitor monitor)
            throws DeviceNotAvailableException;

    /**
     * Attempt to recover the given unresponsive device in bootloader mode.
     *
     * @param monitor the {@link IDeviceStateMonitor} to use.
     * @throws DeviceNotAvailableException if device could not be recovered
     */
    public void recoverDeviceBootloader(IDeviceStateMonitor monitor)
            throws DeviceNotAvailableException;

}

该接口中要三个方法:

recoverDevice:连接不再通信的设备

recoverDeviceRecovery:当手机处于Recovery工程模式下,已经发送信息,但是没有反应,就需要调用该方法再次重连。

recoverDeviceBootloader:恢复没有反馈的设备,与上面不同的是当前设备处于BootLoader模式下。

实现类

cts模式的实现类为WaitDeviceRecovery:

/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.tradefed.device;

import com.android.ddmlib.AdbCommandRejectedException;
import com.android.ddmlib.IDevice;
import com.android.ddmlib.Log;
import com.android.ddmlib.TimeoutException;
import com.android.tradefed.config.Option;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.util.IRunUtil;
import com.android.tradefed.util.RunUtil;

import java.io.IOException;

/**
 * A simple implementation of a {@link IDeviceRecovery} that waits for device to be online and
 * respond to simple commands.
 */
public class WaitDeviceRecovery implements IDeviceRecovery {

    private static final String LOG_TAG = "WaitDeviceRecovery";

    /** the time in ms to wait before beginning recovery attempts */
    protected static final long INITIAL_PAUSE_TIME = 5 * 1000;

    /**
     * The number of attempts to check if device is in bootloader.
     * <p/>
     * Exposed for unit testing
     */
    public static final int BOOTLOADER_POLL_ATTEMPTS = 3;

    // TODO: add a separate configurable timeout per operation
    @Option(name="device-wait-time",
            description="maximum time in ms to wait for a single device recovery command.")
    protected long mWaitTime = 4 * 60 * 1000;

    @Option(name="bootloader-wait-time",
            description="maximum time in ms to wait for device to be in fastboot.")
    protected long mBootloaderWaitTime = 30 * 1000;

    @Option(name="shell-wait-time",
            description="maximum time in ms to wait for device shell to be responsive.")
    protected long mShellWaitTime = 30 * 1000;

    @Option(name = "disable-unresponsive-reboot",
            description = "If this is set, we will not attempt to reboot an unresponsive device" +
            "that is in userspace.  Note that this will have no effect if the device is in " +
            "fastboot or is expected to be in fastboot.")
    protected boolean mDisableUnresponsiveReboot = false;

    /**
     * Get the {@link RunUtil} instance to use.
     * <p/>
     * Exposed for unit testing.
     */
    protected IRunUtil getRunUtil() {
        return RunUtil.getDefault();
    }

    /**
     * Sets the maximum time in ms to wait for a single device recovery command.
     */
    void setWaitTime(long waitTime) {
        mWaitTime = waitTime;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void recoverDevice(IDeviceStateMonitor monitor, boolean recoverUntilOnline)
            throws DeviceNotAvailableException {
        // device may have just gone offline
        // sleep a small amount to give ddms state a chance to settle
        // TODO - see if there is better way to handle this
        Log.i(LOG_TAG, String.format("Pausing for %d for %s to recover",
                INITIAL_PAUSE_TIME, monitor.getSerialNumber()));
        getRunUtil().sleep(INITIAL_PAUSE_TIME);

        // ensure bootloader state is updated
        monitor.waitForDeviceBootloaderStateUpdate();

        if (monitor.getDeviceState().equals(TestDeviceState.FASTBOOT)) {
            Log.i(LOG_TAG, String.format(
                    "Found device %s in fastboot but expected online. Rebooting...",
                    monitor.getSerialNumber()));
            // TODO: retry if failed
            getRunUtil().runTimedCmd(20*1000, "fastboot", "-s", monitor.getSerialNumber(),
                    "reboot");
        }

        // wait for device online
        IDevice device = monitor.waitForDeviceOnline();
        if (device == null) {
            handleDeviceNotAvailable(monitor, recoverUntilOnline);
            return;
        }
        // occasionally device is erroneously reported as online - double check that we can shell
        // into device
        if (!monitor.waitForDeviceShell(mShellWaitTime)) {
            // treat this as a not available device
            handleDeviceNotAvailable(monitor, recoverUntilOnline);
            return;
        }

        if (!recoverUntilOnline) {
            if (monitor.waitForDeviceAvailable(mWaitTime) == null) {
                // device is online but not responsive
                handleDeviceUnresponsive(device, monitor);
            }
        }
    }

    /**
     * Handle situation where device is online but unresponsive.
     * @param monitor
     * @throws DeviceNotAvailableException
     */
    protected void handleDeviceUnresponsive(IDevice device, IDeviceStateMonitor monitor)
            throws DeviceNotAvailableException {
        if (!mDisableUnresponsiveReboot) {
            rebootDevice(device);
        }
        IDevice newdevice = monitor.waitForDeviceOnline();
        if (newdevice == null) {
            handleDeviceNotAvailable(monitor, false);
            return;
        }
        if (monitor.waitForDeviceAvailable(mWaitTime) == null) {
            throw new DeviceUnresponsiveException(String.format(
                    "Device %s is online but unresponsive", monitor.getSerialNumber()));
        }
    }

    /**
     * Handle situation where device is not available.
     *
     * @param monitor the {@link IDeviceStateMonitor}
     * @param recoverTillOnline if true this method should return if device is online, and not
     * check for responsiveness
     * @throws DeviceNotAvailableException
     */
    protected void handleDeviceNotAvailable(IDeviceStateMonitor monitor, boolean recoverTillOnline)
            throws DeviceNotAvailableException {
        throw new DeviceNotAvailableException(String.format("Could not find device %s",
                monitor.getSerialNumber()));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void recoverDeviceBootloader(final IDeviceStateMonitor monitor)
            throws DeviceNotAvailableException {
        // device may have just gone offline
        // wait a small amount to give device state a chance to settle
        // TODO - see if there is better way to handle this
        Log.i(LOG_TAG, String.format("Pausing for %d for %s to recover",
                INITIAL_PAUSE_TIME, monitor.getSerialNumber()));
        getRunUtil().sleep(INITIAL_PAUSE_TIME);

        // poll and wait for device to return to valid state
        long pollTime = mBootloaderWaitTime / BOOTLOADER_POLL_ATTEMPTS;
        for (int i=0; i < BOOTLOADER_POLL_ATTEMPTS; i++) {
            if (monitor.waitForDeviceBootloader(pollTime)) {
                handleDeviceBootloaderUnresponsive(monitor);
                // passed above check, abort
                return;
            } else if (monitor.getDeviceState() == TestDeviceState.ONLINE) {
                handleDeviceOnlineExpectedBootloader(monitor);
                return;
            }
        }
        handleDeviceBootloaderNotAvailable(monitor);
    }

    /**
     * Handle condition where device is online, but should be in bootloader state.
     * <p/>
     * If this method
     * @param monitor
     * @throws DeviceNotAvailableException
     */
    protected void handleDeviceOnlineExpectedBootloader(final IDeviceStateMonitor monitor)
            throws DeviceNotAvailableException {
        Log.i(LOG_TAG, String.format("Found device %s online but expected fastboot.",
            monitor.getSerialNumber()));
        // call waitForDeviceOnline to get handle to IDevice
        IDevice device = monitor.waitForDeviceOnline();
        if (device == null) {
            handleDeviceBootloaderNotAvailable(monitor);
            return;
        }
        rebootDeviceIntoBootloader(device);
        if (!monitor.waitForDeviceBootloader(mBootloaderWaitTime)) {
            throw new DeviceNotAvailableException(String.format(
                    "Device %s not in bootloader after reboot", monitor.getSerialNumber()));
        }
    }

    /**
     * @param monitor
     * @throws DeviceNotAvailableException
     */
    protected void handleDeviceBootloaderUnresponsive(IDeviceStateMonitor monitor)
            throws DeviceNotAvailableException {
        CLog.i("Found device %s in fastboot but potentially unresponsive.",
                monitor.getSerialNumber());
        // TODO: retry reboot
        getRunUtil().runTimedCmd(20*1000, "fastboot", "-s", monitor.getSerialNumber(),
                "reboot-bootloader");
        // wait for device to reboot
        monitor.waitForDeviceNotAvailable(20*1000);
        if (!monitor.waitForDeviceBootloader(mBootloaderWaitTime)) {
            throw new DeviceNotAvailableException(String.format(
                    "Device %s not in bootloader after reboot", monitor.getSerialNumber()));
        }
    }

    /**
     * Reboot device into bootloader.
     *
     * @param device the {@link IDevice} to reboot.
     */
    protected void rebootDeviceIntoBootloader(IDevice device) {
        try {
            device.reboot("bootloader");
        } catch (IOException e) {
            Log.w(LOG_TAG, String.format("failed to reboot %s: %s", device.getSerialNumber(),
                    e.getMessage()));
        } catch (TimeoutException e) {
            Log.w(LOG_TAG, String.format("failed to reboot %s: timeout", device.getSerialNumber()));
        } catch (AdbCommandRejectedException e) {
            Log.w(LOG_TAG, String.format("failed to reboot %s: %s", device.getSerialNumber(),
                    e.getMessage()));
        }
    }

    /**
     * Reboot device into bootloader.
     *
     * @param device the {@link IDevice} to reboot.
     */
    protected void rebootDevice(IDevice device) {
        try {
            device.reboot(null);
        } catch (IOException e) {
            Log.w(LOG_TAG, String.format("failed to reboot %s: %s", device.getSerialNumber(),
                    e.getMessage()));
        } catch (TimeoutException e) {
            Log.w(LOG_TAG, String.format("failed to reboot %s: timeout", device.getSerialNumber()));
        } catch (AdbCommandRejectedException e) {
            Log.w(LOG_TAG, String.format("failed to reboot %s: %s", device.getSerialNumber(),
                    e.getMessage()));
        }
    }

    /**
     * Handle situation where device is not available when expected to be in bootloader.
     *
     * @param monitor the {@link IDeviceStateMonitor}
     * @throws DeviceNotAvailableException
     */
    protected void handleDeviceBootloaderNotAvailable(final IDeviceStateMonitor monitor)
            throws DeviceNotAvailableException {
        throw new DeviceNotAvailableException(String.format(
                "Could not find device %s in bootloader", monitor.getSerialNumber()));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void recoverDeviceRecovery(IDeviceStateMonitor monitor)
            throws DeviceNotAvailableException {
        throw new DeviceNotAvailableException("device recovery not implemented");
    }
}

这个类的方法中具体讲了如何实现重连机制,有兴趣的可以详细了解。我不太感兴趣,就一笔带过了。

时间: 2024-10-24 23:58:36

Cts框架解析(9)-IDeviceRecovery的相关文章

Cts框架解析(5)

解析配置文件 Cts框架分为9大部分: cmd_options:命令行接受的参数选项,command包中. device_requirements:设备相关要求,device包中 device_options:设备参数,device包中 builde_provider:版本提供者,build包中 target_preparer:预置条件准备,targetprep包中 test:测试类型,存在testtype包中 device_recovery:任务执行过程中设备异常后的设备恢复,device包中

Cts框架解析(2)-cts调试环境的搭建

上一篇文章中说了怎样在windows搭建cts以及执行cts进行測试.这篇文章来讲讲怎样在eclipse中配置源代码,进行debug调试. 下载 cts源代码地址:https://android.googlesource.com/platform/cts 能够使用git下载到本地. 文件夹结构 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaXRmb290YmFsbA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFC

Cts框架解析(13)-任务执行过程

因为测试任务是个很复杂的过程,所以要单独拿出来讲,里面还涉及了result_reporter的内容.所以这是一个大块.首先把断点打在CtsTest的run方法中,删除其他断点,重新启动debug模式: 首先会调用checkFields检查一下命令行参数.然后生成plan里的包名信息.(要理解plan的意思,plan就是cts目录下plan文件下的xml文件,它里面配置的entry代表一个测试项,一个测试项里又包含多个测试的case).本程序执行的是Signature计划,我们就来看看这个xml文

Cts框架解析(7)-任务执行的调度室

TestInvocation /** * {@inheritDoc} */ @Override public void invoke(ITestDevice device, IConfiguration config, IRescheduler rescheduler) throws DeviceNotAvailableException, Throwable { try { mStatus = "fetching build"; config.getLogOutput().init(

Cts框架解析(6)-任务的运行

前两篇讲了任务的加入和9大项配置,这篇讲任务的运行. 任务的运行 任务的运行在CommandScheduler的run方法中,所以删除全部的断点,在run方法中打上断点,重新启动启动debug: 先看while循环以下的第一行代码 ExecutableCommand cmd = dequeueConfigCommand(); private ExecutableCommand dequeueConfigCommand() { try { // poll for a command, rather

Cts框架解析(1)-windows下cts配置

环境搭建 下载 cts工具的下载地址:http://source.android.com/compatibility/downloads.html windows选择Android4.4 R3 Compatibility Test Suite (CTS) - ARM下载. 文件夹结构 解压后的文件夹结构例如以下: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaXRmb290YmFsbA==/font/5a6L5L2T/fontsize/400/fil

Cts框架解析(6)-任务的执行

前两篇讲了任务的添加和9大项配置,这篇讲任务的执行. 任务的执行 任务的执行在CommandScheduler的run方法中,所以删除所有的断点,在run方法中打上断点,重启启动debug: 先看while循环下面的第一行代码 ExecutableCommand cmd = dequeueConfigCommand(); private ExecutableCommand dequeueConfigCommand() { try { // poll for a command, rather t

Cts框架解析(8)-IBuildProvider

IBuildProvider接口中定义了三个方法 /* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of th

Cts框架解析(3)

cts是建立在tradefederation项目上的,cts中的tradefed-prebuild.jar就是该项目编译后的jar包.在debug调试的时候少不了这个项目,所以现在开始把这个项目添加到eclipse中. 下载 如果有可以翻墙的话,建议下载最新的版本,我上传的tradefederation应该不是最新的,但是我翻不了墙,所以还是拿这个项目debug. 下载地址:http://download.csdn.net/detail/qhshiniba/8050545 配置 下载后解压后的文