码迷,mamicode.com
首页 > 其他好文 > 详细

Cts框架解析(9)-IDeviceRecovery

时间:2014-10-22 11:03:11      阅读:230      评论:0      收藏:0      [点我收藏+]

标签:cts

当设备处于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");
    }
}

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


Cts框架解析(9)-IDeviceRecovery

标签:cts

原文地址:http://blog.csdn.net/itfootball/article/details/40372615

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!