Cts测试框架笔记

// TODO: currently treat all exceptions the same. In future consider different recovery mechanisms for time out's vs IOExceptions

在android 8.1中 处理异常还没考虑 针对性的处理 都是调用recoverDevice() ,等设备在线 设备不在线就会异常

    protected boolean performDeviceAction(String actionDescription, final DeviceAction action,
            int retryAttempts) throws DeviceNotAvailableException {

        for (int i = 0; i < retryAttempts + 1; i++) {
            try {
                return action.run();
            } catch (TimeoutException e) {
                logDeviceActionException(actionDescription, e);
            } catch (IOException e) {
                logDeviceActionException(actionDescription, e);
            } catch (InstallException e) {
                logDeviceActionException(actionDescription, e);
            } catch (SyncException e) {
                logDeviceActionException(actionDescription, e);
                // a SyncException is not necessarily a device communication problem
                // do additional diagnosis
                if (!e.getErrorCode().equals(SyncError.BUFFER_OVERRUN) &&
                        !e.getErrorCode().equals(SyncError.TRANSFER_PROTOCOL_ERROR)) {
                    // this is a logic problem, doesn't need recovery or to be retried
                    return false;
                }
            } catch (AdbCommandRejectedException e) {
                logDeviceActionException(actionDescription, e);
            } catch (ShellCommandUnresponsiveException e) {
                CLog.w("Device %s stopped responding when attempting %s", getSerialNumber(),
                        actionDescription);
            }
            // TODO: currently treat all exceptions the same. In future consider different recovery
            // mechanisms for time out's vs IOExceptions
            recoverDevice();
        }
    }


    @Override
    public void recoverDevice(IDeviceStateMonitor monitor, boolean recoverUntilOnline)
            throws DeviceNotAvailableException {
        ...
        // wait for device online
        IDevice device = monitor.waitForDeviceOnline(mOnlineWaitTime);
        if (device == null) {
            handleDeviceNotAvailable(monitor, recoverUntilOnline);
            // function returning implies that recovery is successful, check battery level here
            checkMinBatteryLevel(getDeviceAfterRecovery(monitor));
            return;
        }
        ...
    }

CTS的启动


相关源码文件

tools//tradefederation/core/src/com/android/tradefed/device/DeviceManager.java              // init
tools/tradefederation/core/src/com/android/tradefed/device/ManagedTestDeviceFactory.java    // createDevice return IManagedTestDevice; 这里创建不同类型的设备 RemoteAndroidDevice NativeDevice 等等 
tools/tradefederation/core/src/com/android/tradefed/device/NativeDevice.java   
tools/tradefederation/core/src/com/android/tradefed/device/DeviceStateMonitor.java  
tools/tradefederation/core/src/com/android/tradefed/device/NativeDeviceStateMonitor.java    // waitForDeviceState 监控设备在线, 提供setState 方法供设置

DeviceManager#init()

  • 创建 ManagedTestDeviceFactory
  • 创建 ManagedDeviceList
  • 调用 startAdbBridgeAndDependentServices() 初始化 adb
    protected DeviceMonitorMultiplexer mDvcMon = new DeviceMonitorMultiplexer();

    @Override
    public void init(IDeviceSelection globalDeviceFilter,
            List<IDeviceMonitor> globalDeviceMonitors) {
        init(globalDeviceFilter, globalDeviceMonitors,
                new ManagedTestDeviceFactory(mFastbootEnabled, DeviceManager.this, mDvcMon));   
    }

    /**
     * Initialize the device manager. This must be called once and only once before any other
     * methods are called.
     */
    public synchronized void init(IDeviceSelection globalDeviceFilter,
            List<IDeviceMonitor> globalDeviceMonitors, IManagedTestDeviceFactory deviceFactory) {
        // .conf  .xml testcase配置文件解析
        if (globalDeviceFilter == null) {
            globalDeviceFilter = getGlobalConfig().getDeviceRequirements();
        }

        if (globalDeviceMonitors == null) {
            globalDeviceMonitors = getGlobalConfig().getDeviceMonitors();
        }

        mGlobalHostMonitors = getGlobalConfig().getHostMonitors();
        if (mGlobalHostMonitors != null) {
            for (IHostMonitor hm : mGlobalHostMonitors) {
                hm.start();
            }
        }

        mIsInitialized = true;
        mGlobalDeviceFilter = globalDeviceFilter;
        if (globalDeviceMonitors != null) {
            mDvcMon.addMonitors(globalDeviceMonitors);
        }
        mManagedDeviceList = new ManagedDeviceList(deviceFactory);
        ...
        // don't start adding devices until fastboot support has been established
        startAdbBridgeAndDependentServices();
}

配置读取

  • getGlobalConfig()#getHostMonitors()
  • getGlobalConfig()#getDeviceRequirements()
  • getGlobalConfig()#getDeviceMonitors()

实现类: tools/tradefederation/core/src/com/android/tradefed/config/ConfigurationFactory.java

createConfigurationFromArgs() --> internalCreateConfigurationFromArgs()
                                           ||
                                           \/
                                   configDef.createConfiguration() -->  new Configuration()
     public Configuration(String name, String description) {
        mName = name;
        mDescription = description;
        mConfigMap = new LinkedHashMap<String, List<Object>>();
        setDeviceConfig(new DeviceConfigurationHolder(ConfigurationDef.DEFAULT_DEVICE_NAME));
        setCommandOptions(new CommandOptions());
        setTest(new StubTest());
        setLogOutput(new StdoutLogger());
        setLogSaver(new FileSystemLogSaver()); // FileSystemLogSaver saves to tmp by default.
        setTestInvocationListener(new TextResultReporter());
        setMultiTargetPreparer(new StubMultiTargetPreparer());
        setSystemStatusCheckers(new ArrayList<ISystemStatusChecker>());
        setConfigurationDescriptor(new ConfigurationDescriptor());
        setProfiler(new StubTestProfiler());
        setDeviceMetricCollectors(new ArrayList<>());
    }

startAdbBridgeAndDependentServices()

  • 初始化AdbBridge.init()
  • AdbBridge设置回调ManagedDeviceListener
  • 添加设备addTcpDevices()

AdbBridge.init() 依赖ddmlib,实际是对ddmlib的初始化

    /** Initialize adb connection and services depending on adb connection. */
    private synchronized void startAdbBridgeAndDependentServices() {
        // TODO: Temporarily increase default timeout as workaround for syncFiles timeouts
        DdmPreferences.setTimeOut(120 * 1000);
        mAdbBridge = createAdbBridge();
        mManagedDeviceListener = new ManagedDeviceListener();
        // It's important to add the listener before initializing the ADB bridge to avoid a race
        // condition when detecting devices.
        mAdbBridge.addDeviceChangeListener(mManagedDeviceListener); //设置回调
        if (mDvcMon != null) {
            mDvcMon.setDeviceLister(new DeviceLister() {
                @Override
                public List<DeviceDescriptor> listDevices() {
                    return listAllDevices();
                }
            });
            mDvcMon.run();
        }

        mAdbBridge.init(false /* client support */, mAdbPath);
        
        addEmulators();
        addNullDevices();
        addTcpDevices();

        List<IMultiDeviceRecovery> recoverers = getGlobalConfig().getMultiDeviceRecoveryHandlers();
        if (recoverers != null) {
            for (IMultiDeviceRecovery recoverer : recoverers) {
                recoverer.setFastbootPath(mFastbootPath);
            }
            mDeviceRecoverer = new DeviceRecoverer(recoverers);
            startDeviceRecoverer();
        }
    }

ManagedDeviceListener回调处理 ddmlib 负责回调,然后通过ManagedDeviceList.handleDeviceEvent()更新设备状态

    private class ManagedDeviceListener implements IDeviceChangeListener {

        @Override
        public void deviceChanged(IDevice idevice, int changeMask) {
            if ((changeMask & IDevice.CHANGE_STATE) != 0) {
                IManagedTestDevice testDevice = mManagedDeviceList.findOrCreate(idevice);
                if (testDevice == null) {
                    return;
                }
                TestDeviceState newState = TestDeviceState.getStateByDdms(idevice.getState());
                CLog.d("Device changed mask " + changeMask + " newState " + newState);
                testDevice.setDeviceState(newState);
                if (newState == TestDeviceState.ONLINE) {
                    DeviceEventResponse r = mManagedDeviceList.handleDeviceEvent(testDevice,
                            DeviceEvent.STATE_CHANGE_ONLINE);
                    if (r.stateChanged && r.allocationState ==
                            DeviceAllocationState.Checking_Availability) {
                        checkAndAddAvailableDevice(testDevice);
                    }
                } else if (DeviceState.OFFLINE.equals(idevice.getState()) ||
                        DeviceState.UNAUTHORIZED.equals(idevice.getState())) {
                    // handle device changing to offline or unauthorized.
                    mManagedDeviceList.handleDeviceEvent(testDevice,
                            DeviceEvent.STATE_CHANGE_OFFLINE);
                }
            }
        }

        ...
}

创建设备

第一次肯定是不存设备, 所以会调用 ManagedTestDeviceFactory.createDevice(idevice) 实际返回的是 NativeDevice 对象

addTcpDevices() ---> addAvailableDevice(new TcpDevice("tcp-device-0")) 
                                         ||
                                         \/                              
                     ManagedDeviceList.findOrCreate(TcpDevice idevice)  =======> ManagedTestDeviceFactory.createDevice(idevice) 
                                                                                                      ||
                                                                                                      \/
new RemoteAndroidDevice(idevice) --> new TestDevice(idevice,new DeviceStateMonitor(), mAllocationMonitor) --> new NativeDevice(idevice,new DeviceStateMonitor(), mAllocationMonitor)

     * Add placeholder objects for the max number of tcp devices that can be connected
     */

    private static final String TCP_DEVICE_SERIAL_PREFIX = "tcp-device";

    private void addTcpDevices() {
        for (int i = 0; i < mNumTcpDevicesSupported; i++) {
            addAvailableDevice(TcpDevice(String.format("%s-%d", TCP_DEVICE_SERIAL_PREFIX, i)));
        }
    }  

    public void addAvailableDevice(IDevice stubDevice) {
        IManagedTestDevice d = mManagedDeviceList.findOrCreate(stubDevice);
        if (d != null) {
            mManagedDeviceList.handleDeviceEvent(d, DeviceEvent.FORCE_AVAILABLE); //设置成FORCE_AVAILABLE
        } else {
            CLog.e("Could not create stub device");            
        }
    } 

ManagedDeviceList.findOrCreate(IDevice idevice) A thread-safe data structure that holds all devices known to

如果没有这设备就会调用上面的 ManagedTestDeviceFactory#createDevice(IDevice idevice) ,第一次这里肯定没有

// A thread-safe data structure that holds all devices known to {@link DeviceManager}.
    public IManagedTestDevice findOrCreate(IDevice idevice) {
        if (!isValidDeviceSerial(idevice.getSerialNumber())) {
            return null;
        }
        mListLock.lock();
        try {
            IManagedTestDevice d = find(idevice.getSerialNumber());
            if (d == null || DeviceAllocationState.Unavailable.equals(d.getAllocationState())) {
                mList.remove(d);
                d = mDeviceFactory.createDevice(idevice);
                mList.add(d);
            }
            return d;
        } finally {
            mListLock.unlock();
        }
    }

ManagedTestDeviceFactory#createDevice(IDevice idevice) 创建不同类型的设备 RemoteAndroidDevice NativeDevice 等等

 @Override
    public IManagedTestDevice createDevice(IDevice idevice) {
        IManagedTestDevice testDevice = null;
        if (idevice instanceof TcpDevice || isTcpDeviceSerial(idevice.getSerialNumber())) {
            // Special device for Tcp device for custom handling.
            // 后面的流程是 new RemoteAndroidDevice() --> new TestDevice() --> new NativeDevice()
            testDevice = new RemoteAndroidDevice(idevice,
                    new DeviceStateMonitor(mDeviceManager, idevice, mFastbootEnabled),
                    mAllocationMonitor);
            testDevice.setDeviceState(TestDeviceState.NOT_AVAILABLE);
        } else if (!checkFrameworkSupport(idevice)) {
            // Brillo device instance tier 1 (no framework support)
            testDevice = new NativeDevice(idevice,
                    new NativeDeviceStateMonitor(mDeviceManager, idevice, mFastbootEnabled),
                    mAllocationMonitor);
        } else {
            // Default to-go device is Android full stack device.
            testDevice = new TestDevice(idevice,
                    new DeviceStateMonitor(mDeviceManager, idevice, mFastbootEnabled),
                    mAllocationMonitor);
        }
        ....
        return testDevice;
}

handleAllocationEvent流程

DeviceManager.checkAndAddAvailableDevice() --> ManagedDeviceList.handleDeviceEvent() --> NativeDevice.handleAllocationEvent() --> DeviceAllocationEventHandler.handleDeviceEvent()

    public DeviceEventResponse handleAllocationEvent(DeviceEvent event) {

        // keep track of whether state has actually changed or not
        boolean stateChanged = false;
        DeviceAllocationState newState;
        DeviceAllocationState oldState = mAllocationState;
        mAllocationStateLock.lock();
        try {
            // update oldState here, just in case in changed before we got lock
            oldState = mAllocationState;
            newState = mAllocationState.handleDeviceEvent(event);
            if (oldState != newState) {
                // state has changed! record this fact, and store the new state
                stateChanged = true;
                mAllocationState = newState;
            }
        } finally {
            mAllocationStateLock.unlock();
        }
        if (stateChanged && mAllocationMonitor != null) {
            // state has changed! Lets inform the allocation monitor listener
            mAllocationMonitor.notifyDeviceStateChange(getSerialNumber(), oldState, newState);
        }
        return new DeviceEventResponse(newState, stateChanged);
    }

mAllocationMonitor.notifyDeviceStateChange()流程

// tools/tradefederation/core/src/com/android/tradefed/command/CommandScheduler.java

IDeviceManager manager = getDeviceManager();
manager.addDeviceMonitor(new AvailDeviceMonitor());

        // AvailDeviceMonitor.notifyDeviceStateChange()
        @Override
        public void notifyDeviceStateChange(String serial, DeviceAllocationState oldState,
                DeviceAllocationState newState) {
            if (newState.equals(DeviceAllocationState.Available)) {
                // new avail device was added, wake up scheduler
                mCommandProcessWait.signalEventReceived();
            }   
        }
        
        // Available才唤醒
        public synchronized void signalEventReceived() {
            mEventReceived = true;
            notifyAll();
        }
  
posted @ 2022-12-08 20:06  梦过无声  阅读(120)  评论(0编辑  收藏  举报