<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # 設備恢復 ## 類關系 ![](https://box.kancloud.cn/2016-01-09_56911ddd1b454.jpg) ## 理解 4個分類中,AbortRecovery和StubDeviceRecovery2個類都是直接繼承方法,直接做報錯處理。但是報錯的信息體現了他們的不同點,一個是放棄恢復,一個是不能恢復。還有客觀世界中的區別:好比在說,我能上清華,只是我不上而已。 那么就剩下另外2個類。ReconnectingRecovery和WaitDeviceRecovery。一個是重連,一個實等待設備恢復。2者有什么區別,去具體看方法里的定義吧。 ## 代碼 AbortRecovery:放棄恢復。就是我不恢復 ~~~ private static class AbortRecovery implements IDeviceRecovery { /** * {@inheritDoc} */ @Override public void recoverDevice(IDeviceStateMonitor monitor, boolean recoverUntilOnline) throws DeviceNotAvailableException { throw new DeviceNotAvailableException("aborted test session"); } /** * {@inheritDoc} */ @Override public void recoverDeviceBootloader(IDeviceStateMonitor monitor) throws DeviceNotAvailableException { throw new DeviceNotAvailableException("aborted test session"); } /** * {@inheritDoc} */ @Override public void recoverDeviceRecovery(IDeviceStateMonitor monitor) throws DeviceNotAvailableException { throw new DeviceNotAvailableException("aborted test session"); } } ~~~ StubDeviceRecovery:為虛擬設備定義的,意思是:我不能恢復。 ~~~ public class StubDeviceRecovery implements IDeviceRecovery { /** * {@inheritDoc} */ @Override public void recoverDevice(IDeviceStateMonitor monitor, boolean recoverUntilOnline) throws DeviceNotAvailableException { throw new DeviceNotAvailableException("device recovery not implemented"); } /** * {@inheritDoc} */ @Override public void recoverDeviceBootloader(IDeviceStateMonitor monitor) throws DeviceNotAvailableException { throw new DeviceNotAvailableException("device recovery not implemented"); } /** * {@inheritDoc} */ @Override public void recoverDeviceRecovery(IDeviceStateMonitor monitor) throws DeviceNotAvailableException { throw new DeviceNotAvailableException("device recovery not implemented"); } } ~~~ ReconnectingRecovery:重新連接設備。用于wifi連接設備的時候,如果短線了,調用adb connect的命令來連接設備。 ~~~ 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(); } } ~~~ 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,最新獲取過fastboot devices信息 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"); } } ~~~ ## 重點 現在著重來理解WaitDeviceRecovery中的方法。 ### recoverDevice方法 ~~~ /** * {@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,最新獲取過fastboot devices信息 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); } } } ~~~ 1.首先等待5秒鐘,是為了給adb足夠的時間先自己處理一下設備斷線問題。(adb有自動恢復功能)。 2.我們要等待最新一次的fastboot監聽器的執行結果,這個在上一篇文章講過fastboot監聽器是做什么用的。 3.判斷目前設備斷線的原因是否是因為進入到了fastboot模式下。如果是的話,執行fastboot reboot操作重啟設備。 4.等待設備恢復到在線狀態(具體怎么等待的,我會在DeviceMonitor中講解)。 5.如果等待過后,設備沒有恢復到在線狀態,則調用handleDeviceNotAvailable方法,直接拋出錯誤。 6.如果設備正常恢復到online狀態。再次通過adb命令來檢測其正常性,雙重驗證。如果驗證不通過也需要拋出錯誤。 7.如果第二次驗證通過,是否需要等待設備處于有效狀態,有效狀態和在線狀態的區別在于:在線不等于就可以用于測試。可以用于測試的測試需要經過很多中檢測。這個也會在以后講解。 8.如果做了等待設備直到處于有效狀態的操作后,設備沒有反饋正確的結果,說明設備沒有處于有效狀態,這個時候我們就需要調用handleDeviceUnresponsive() ~~~ 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())); } } ~~~ 9.在上面的方法中,會先判斷是否可以重啟,如果可以的話,先重啟一下設備。 10.然后重復一遍4~7的步驟 11.如果還沒成功,就直接報錯了。 上面的步驟中在執行設備恢復到設備處于在線狀態的的過程中,執行了2次,稱為retry的動作。再試一次,可以使成功的概率大一點。 ### recoverDeviceBootloader方法 ~~~ @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); } ~~~ 1.第一步和上面的意義,等待一段時間,讓adb先自己處理。 2.計算重復執行的次數,用總時間/執行的次數,等待每次執行所用的時間。 3.執行等待設備處于BootLoader模式,也就是fastboot模式。 4.如果成功進入fastboot模式,則直接返回,如果設備處于online模式,則調用handleDeviceOnlineExpectedBootloader方法 ~~~ 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())); } } ~~~ 5.進入該方法后,首先通過直接monitor.waitForDeviceOnline()來得到該設備,因為該設備就已經處于online,這里調用只是為了得到IDevice. 6.如果這個時候得到的設備為null,直接拋出錯誤。 7.然后重啟設備,進入fastboot模式。 8.然后再次等待設備處于fastboot模式,如果成功,方法結束,回到recoverDeviceBootloader中,然后recoverDeviceBootloader也結束,返回。如果失敗,直接拋出異常。 9.重復3~8的過程,如果循環結束后,還無法進入fastboot模式,直接拋出異常。 ### recoverDeviceRecovery方法 因為不可能執行卡刷,所以該方法直接拋出異常。 ~~~ public void recoverDeviceRecovery(IDeviceStateMonitor monitor) throws DeviceNotAvailableException { throw new DeviceNotAvailableException("device recovery not implemented"); } ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看