1/* 2 * Copyright (C) 2013 DroidDriver committers 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.google.android.droiddriver.uiautomation; 18 19import android.app.UiAutomation; 20import android.app.Instrumentation; 21import android.graphics.Bitmap; 22import android.os.SystemClock; 23import android.view.accessibility.AccessibilityNodeInfo; 24 25import com.google.android.droiddriver.base.AbstractDroidDriver; 26import com.google.android.droiddriver.exceptions.TimeoutException; 27import com.google.common.primitives.Longs; 28 29/** 30 * Implementation of a DroidDriver that is driven via the accessibility layer. 31 */ 32public class UiAutomationDriver extends AbstractDroidDriver { 33 // TODO: magic const from UiAutomator, but may not be useful 34 /** 35 * This value has the greatest bearing on the appearance of test execution 36 * speeds. This value is used as the minimum time to wait before considering 37 * the UI idle after each action. 38 */ 39 private static final long QUIET_TIME_TO_BE_CONSIDERD_IDLE_STATE = 500;// ms 40 41 private final UiAutomationContext context; 42 private final UiAutomation uiAutomation; 43 44 public UiAutomationDriver(Instrumentation instrumentation) { 45 super(instrumentation); 46 this.uiAutomation = instrumentation.getUiAutomation(); 47 this.context = new UiAutomationContext(uiAutomation); 48 } 49 50 @Override 51 protected UiAutomationElement getNewRootElement() { 52 return context.getUiElement(getRootNode()); 53 } 54 55 @Override 56 protected UiAutomationContext getContext() { 57 return context; 58 } 59 60 private AccessibilityNodeInfo getRootNode() { 61 long timeoutMillis = getPoller().getTimeoutMillis(); 62 try { 63 uiAutomation.waitForIdle(QUIET_TIME_TO_BE_CONSIDERD_IDLE_STATE, timeoutMillis); 64 } catch (java.util.concurrent.TimeoutException e) { 65 throw new TimeoutException(e); 66 } 67 long end = SystemClock.uptimeMillis() + timeoutMillis; 68 while (true) { 69 AccessibilityNodeInfo root = uiAutomation.getRootInActiveWindow(); 70 if (root != null) { 71 return root; 72 } 73 long remainingMillis = end - SystemClock.uptimeMillis(); 74 if (remainingMillis < 0) { 75 throw new TimeoutException( 76 String.format("Timed out after %d milliseconds waiting for root AccessibilityNodeInfo", 77 timeoutMillis)); 78 } 79 SystemClock.sleep(Longs.min(250, remainingMillis)); 80 } 81 } 82 83 @Override 84 protected Bitmap takeScreenshot() { 85 return uiAutomation.takeScreenshot(); 86 } 87} 88