| /* |
| * Copyright (C) 2011 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.tradefed.log.LogUtil.CLog; |
| import com.android.tradefed.util.IRunUtil; |
| import com.android.tradefed.util.RunUtil; |
| |
| /** |
| * Recovers a device by re-establishing a TCP connection via the adb server on |
| * the host. |
| */ |
| public class ReconnectingRecovery implements IDeviceRecovery { |
| |
| private static final int ADB_TIMEOUT = 2 * 60 * 1000; |
| private static final int CONNECTION_ATTEMPTS = 5; |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void recoverDevice(IDeviceStateMonitor monitor, boolean recoverUntilOnline) |
| throws DeviceNotAvailableException { |
| String serial = monitor.getSerialNumber(); |
| |
| // disconnect - many versions of adb client have stale TCP connection |
| // status |
| getRunUtil().runTimedCmd(ADB_TIMEOUT, "adb", "disconnect", serial); |
| |
| // try to reconnect |
| int attempt = 1; |
| do { |
| CLog.i("Trying to reconnect with device " + serial + " / attempt " + attempt); |
| getRunUtil().runTimedCmd(ADB_TIMEOUT, "adb", "connect", serial); |
| } while (monitor.waitForDeviceOnline() == null && ++attempt <= CONNECTION_ATTEMPTS); |
| |
| String errMsg = "Could not recover device " + serial + " after " + --attempt + " attempts"; |
| |
| // occasionally device is erroneously reported as online - double check |
| // that we can shell into device |
| if (!monitor.waitForDeviceShell(10 * 1000)) { |
| throw new DeviceUnresponsiveException(errMsg); |
| } |
| |
| if (!recoverUntilOnline) { |
| if (monitor.waitForDeviceAvailable() == null) { |
| throw new DeviceUnresponsiveException(errMsg); |
| } |
| } |
| |
| CLog.v("Successfully reconnected with device " + serial); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void recoverDeviceBootloader(IDeviceStateMonitor monitor) |
| throws DeviceNotAvailableException { |
| throw new java.lang.UnsupportedOperationException( |
| "This implementation can't recover a device in bootloader mode."); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * <p> |
| * This implementation assumes devices in recovery mode can't be talked to |
| * at all, so it will try to recover a device and leave it in fully booted |
| * mode. |
| */ |
| @Override |
| public void recoverDeviceRecovery(IDeviceStateMonitor monitor) |
| throws DeviceNotAvailableException { |
| recoverDevice(monitor, false); |
| } |
| |
| /** |
| * Get the {@link RunUtil} instance to use. |
| * <p/> |
| * Exposed for unit testing. |
| */ |
| IRunUtil getRunUtil() { |
| return RunUtil.getDefault(); |
| } |
| } |