When the device is in the offline state, the CTS framework calls the Idevicerecovery interface class to do the corresponding recovery work.
interface
/* Copyright (C) The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "Licens
E ");
* You are not a use this file except in compliance with the License. * Obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * unless required by a Pplicable law or agreed to in writing, software * Distributed under the License are distributed on a "as is" BASIS, * WI
Thout 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 which has gone offline. */public interface Idevicerecovery {/** * attempt to recover the given device so can no longer be communicat
Ed with.
* <p/> * Method should block and only return if 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 Idevic
Estatemonitor#waitfordeviceavailable ()} succeeds. * @throws Devicenotavailableexception If device could not being recovered */public void Recoverdevice (Idevicestatem
Onitor 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 being recovered */public void Recoverdevicerecovery (Idevi
Cestatemonitor 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 being recovered */public void Recoverdevicebootloader (IDe
Vicestatemonitor monitor) throws devicenotavailableexception;
}
There are three methods in this interface:
Recoverdevice: Connecting devices that are no longer communicating
Recoverdevicerecovery: When the phone is in recovery engineering mode, the message has been sent, but there is no response, you need to call the method to re-connect again.
Recoverdevicebootloader: Restore the device without feedback, unlike above, the current device is in bootloader mode.
Implementation Class
The implementation class for the CTS pattern is waitdevicerecovery:
/* Copyright (C) The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "Licens
E ");
* You are not a use this file except in compliance with the License. * Obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * unless required by a Pplicable law or agreed to in writing, software * Distributed under the License are distributed on a "as is" BASIS, * WI
Thout 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}, waits for device to is online and * respond to Simple CO
Mmands. */public class Waitdevicerecovery implements Idevicerecovery {private static final String Log_tag = "Waitdevicereco
Very "; /** 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 are 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= "M
Aximum 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 is 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'll not attempt-reboot an unresponsive Device "+" that's in userspace.
Note that this would have no effect if the device was in "+" fastboot or was expected to being 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 voidRecoverdevice (Idevicestatemonitor Monitor, Boolean recoveruntilonline) throws Devicenotavailableexception { Device may has just gone offline//sleep a small amount to give Ddms state a chance to settle/ /Todo-see If there is better a-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, 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 and not responsive handledeviceunresponsive (device, monitor);
}}}/** * Handle situation where device is online but unresponsive. * @param monitor * @throws devicenotavailableexception */protected void handledeviceunresponsive (IDevice de ViCE, 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 (Strin
G.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 */Protec Ted 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 mo Nitor) throws Devicenotavailableexception {//device may have just gone offline//Wait a SMA ll amount to give device state a chance to settle//Todo-see If there is better a-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_attempt
S
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 (Moni
TOR);
Return
}} handledevicebootloadernotavailable (monitor);
}/** * Handle condition where device is online, but should was in the bootloader state. * <p/> * If This method * @param monitor * @throws devicenotavailableexception */protected void Handledeviceonlineexpectedbootloader (final idevicestatemonitor monitor) throws Devicenotavailableexceptio n {log.i (Log_tag, String.Format ("Found device%s online but expected fastboot."), Monitor.getserialnum
ber ()));
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.form
At ("Device%s not in bootloader after reboot", Monitor.getserialnumber ())); }}/** * @param monitor * @throws devicenotavailableexception */protected void HANDLEDEVICEB Ootloaderunresponsive (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.ge
Tserialnumber ()));
}}/** * 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.getserialnumb
ER (), e.getmessage ())); } catch (TimeoutException e) {LOG.W (Log_tag, String.Format ("Failed to reboot%s:timeout", Device.getserialnu
Mber ())); } catch (Adbcommandrejectedexception e) {LOG.W (Log_tag, String.Format ("Failed to reboot%s:%s", Device.getse
Rialnumber (), 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.getserialnu
Mber ())); } catch (Adbcommandrejectedexception e) {LOG.W (Log_tag, String.Format ("Failed to reboot%s:%s", Device.getse
Rialnumber (), E.getmessage ()));
}}/** * Handle situation where device is not available when expected to was in bootloader. * * @param monitor the {@link idevicestatemonitor} * @throws devicenotavailableexception */protected V
OID 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 impleme
Nted ");
}
}
The method of this class specifically describes how to implement the re-connect mechanism, interested can be detailed understanding. I'm not very interested, just a pen.