1cddda72410c992a12db61cef26713b498e31fea4Thanh Le/* 2cddda72410c992a12db61cef26713b498e31fea4Thanh Le * Copyright (C) 2013 DroidDriver committers 3cddda72410c992a12db61cef26713b498e31fea4Thanh Le * 4cddda72410c992a12db61cef26713b498e31fea4Thanh Le * Licensed under the Apache License, Version 2.0 (the "License"); 5cddda72410c992a12db61cef26713b498e31fea4Thanh Le * you may not use this file except in compliance with the License. 6cddda72410c992a12db61cef26713b498e31fea4Thanh Le * You may obtain a copy of the License at 7cddda72410c992a12db61cef26713b498e31fea4Thanh Le * 8cddda72410c992a12db61cef26713b498e31fea4Thanh Le * http://www.apache.org/licenses/LICENSE-2.0 9cddda72410c992a12db61cef26713b498e31fea4Thanh Le * 10cddda72410c992a12db61cef26713b498e31fea4Thanh Le * Unless required by applicable law or agreed to in writing, software 11cddda72410c992a12db61cef26713b498e31fea4Thanh Le * distributed under the License is distributed on an "AS IS" BASIS, 12cddda72410c992a12db61cef26713b498e31fea4Thanh Le * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13cddda72410c992a12db61cef26713b498e31fea4Thanh Le * See the License for the specific language governing permissions and 14cddda72410c992a12db61cef26713b498e31fea4Thanh Le * limitations under the License. 15cddda72410c992a12db61cef26713b498e31fea4Thanh Le */ 16cddda72410c992a12db61cef26713b498e31fea4Thanh Le 17cddda72410c992a12db61cef26713b498e31fea4Thanh Lepackage com.google.android.droiddriver.instrumentation; 18cddda72410c992a12db61cef26713b498e31fea4Thanh Le 19115eb39036a7a4e500dc94b57975a5693861f654Tony Wickhamimport android.app.Activity; 20cddda72410c992a12db61cef26713b498e31fea4Thanh Leimport android.app.Instrumentation; 21e2660726a43b1a68729d736f6ffa0332ab152498Kevin Jinimport android.graphics.Bitmap; 225838b1a067427865c3ec8cc33a5dfa64ba05407fKevin Jinimport android.os.SystemClock; 23cddda72410c992a12db61cef26713b498e31fea4Thanh Leimport android.view.View; 24cddda72410c992a12db61cef26713b498e31fea4Thanh Le 250d7b67b43f83536708a6ae0330e739744049a48eKevin Jinimport com.google.android.droiddriver.base.AbstractDroidDriver; 265838b1a067427865c3ec8cc33a5dfa64ba05407fKevin Jinimport com.google.android.droiddriver.exceptions.TimeoutException; 27115eb39036a7a4e500dc94b57975a5693861f654Tony Wickhamimport com.google.android.droiddriver.util.ActivityUtils; 285838b1a067427865c3ec8cc33a5dfa64ba05407fKevin Jinimport com.google.common.primitives.Longs; 290d7b67b43f83536708a6ae0330e739744049a48eKevin Jin 30cddda72410c992a12db61cef26713b498e31fea4Thanh Le/** 31cddda72410c992a12db61cef26713b498e31fea4Thanh Le * Implementation of a UiDriver that is driven via instrumentation. 32cddda72410c992a12db61cef26713b498e31fea4Thanh Le */ 33cddda72410c992a12db61cef26713b498e31fea4Thanh Lepublic class InstrumentationDriver extends AbstractDroidDriver { 3452107c27b6b0f2b0fdfec995784c73746bb95c4eKevin Jin private final InstrumentationContext context; 35cddda72410c992a12db61cef26713b498e31fea4Thanh Le 36cddda72410c992a12db61cef26713b498e31fea4Thanh Le public InstrumentationDriver(Instrumentation instrumentation) { 3721a0001e2426644dd68e6140b5873ebaeafcc3dcKevin Jin super(instrumentation); 3852107c27b6b0f2b0fdfec995784c73746bb95c4eKevin Jin this.context = new InstrumentationContext(instrumentation); 39cddda72410c992a12db61cef26713b498e31fea4Thanh Le } 40cddda72410c992a12db61cef26713b498e31fea4Thanh Le 41cddda72410c992a12db61cef26713b498e31fea4Thanh Le @Override 4221a0001e2426644dd68e6140b5873ebaeafcc3dcKevin Jin protected ViewElement getNewRootElement() { 43c91cb19438c6ef8ecd794664bf1f879725866bb9Kevin Jin return context.getUiElement(findRootView()); 44c91cb19438c6ef8ecd794664bf1f879725866bb9Kevin Jin } 45115eb39036a7a4e500dc94b57975a5693861f654Tony Wickham 4621a0001e2426644dd68e6140b5873ebaeafcc3dcKevin Jin @Override 4721a0001e2426644dd68e6140b5873ebaeafcc3dcKevin Jin protected InstrumentationContext getContext() { 4821a0001e2426644dd68e6140b5873ebaeafcc3dcKevin Jin return context; 4921a0001e2426644dd68e6140b5873ebaeafcc3dcKevin Jin } 5021a0001e2426644dd68e6140b5873ebaeafcc3dcKevin Jin 51c91cb19438c6ef8ecd794664bf1f879725866bb9Kevin Jin private View findRootView() { 52c91cb19438c6ef8ecd794664bf1f879725866bb9Kevin Jin Activity runningActivity = getRunningActivity(); 53cddda72410c992a12db61cef26713b498e31fea4Thanh Le View[] views = RootFinder.getRootViews(); 54115eb39036a7a4e500dc94b57975a5693861f654Tony Wickham if (views.length > 1) { 55c91cb19438c6ef8ecd794664bf1f879725866bb9Kevin Jin for (View view : views) { 56c91cb19438c6ef8ecd794664bf1f879725866bb9Kevin Jin if (view.hasWindowFocus()) { 57c91cb19438c6ef8ecd794664bf1f879725866bb9Kevin Jin return view; 58c91cb19438c6ef8ecd794664bf1f879725866bb9Kevin Jin } 59c91cb19438c6ef8ecd794664bf1f879725866bb9Kevin Jin } 60115eb39036a7a4e500dc94b57975a5693861f654Tony Wickham } 61c91cb19438c6ef8ecd794664bf1f879725866bb9Kevin Jin return runningActivity.getWindow().getDecorView(); 62cddda72410c992a12db61cef26713b498e31fea4Thanh Le } 63cddda72410c992a12db61cef26713b498e31fea4Thanh Le 645838b1a067427865c3ec8cc33a5dfa64ba05407fKevin Jin private Activity getRunningActivity() { 655838b1a067427865c3ec8cc33a5dfa64ba05407fKevin Jin long timeoutMillis = getPoller().getTimeoutMillis(); 665838b1a067427865c3ec8cc33a5dfa64ba05407fKevin Jin long end = SystemClock.uptimeMillis() + timeoutMillis; 675838b1a067427865c3ec8cc33a5dfa64ba05407fKevin Jin while (true) { 6821a0001e2426644dd68e6140b5873ebaeafcc3dcKevin Jin instrumentation.waitForIdleSync(); 695838b1a067427865c3ec8cc33a5dfa64ba05407fKevin Jin Activity runningActivity = ActivityUtils.getRunningActivity(); 705838b1a067427865c3ec8cc33a5dfa64ba05407fKevin Jin if (runningActivity != null) { 715838b1a067427865c3ec8cc33a5dfa64ba05407fKevin Jin return runningActivity; 725838b1a067427865c3ec8cc33a5dfa64ba05407fKevin Jin } 735838b1a067427865c3ec8cc33a5dfa64ba05407fKevin Jin long remainingMillis = end - SystemClock.uptimeMillis(); 745838b1a067427865c3ec8cc33a5dfa64ba05407fKevin Jin if (remainingMillis < 0) { 755838b1a067427865c3ec8cc33a5dfa64ba05407fKevin Jin throw new TimeoutException(String.format( 765838b1a067427865c3ec8cc33a5dfa64ba05407fKevin Jin "Timed out after %d milliseconds waiting for foreground activity", timeoutMillis)); 775838b1a067427865c3ec8cc33a5dfa64ba05407fKevin Jin } 785838b1a067427865c3ec8cc33a5dfa64ba05407fKevin Jin SystemClock.sleep(Longs.min(250, remainingMillis)); 795838b1a067427865c3ec8cc33a5dfa64ba05407fKevin Jin } 805838b1a067427865c3ec8cc33a5dfa64ba05407fKevin Jin } 815838b1a067427865c3ec8cc33a5dfa64ba05407fKevin Jin 82e2660726a43b1a68729d736f6ffa0332ab152498Kevin Jin private static class ScreenshotRunnable implements Runnable { 83e2660726a43b1a68729d736f6ffa0332ab152498Kevin Jin private final View rootView; 84e2660726a43b1a68729d736f6ffa0332ab152498Kevin Jin private Bitmap screenshot; 85e2660726a43b1a68729d736f6ffa0332ab152498Kevin Jin 86e2660726a43b1a68729d736f6ffa0332ab152498Kevin Jin private ScreenshotRunnable(View rootView) { 87e2660726a43b1a68729d736f6ffa0332ab152498Kevin Jin this.rootView = rootView; 88e2660726a43b1a68729d736f6ffa0332ab152498Kevin Jin } 89e2660726a43b1a68729d736f6ffa0332ab152498Kevin Jin 90e2660726a43b1a68729d736f6ffa0332ab152498Kevin Jin @Override 91e2660726a43b1a68729d736f6ffa0332ab152498Kevin Jin public void run() { 92e2660726a43b1a68729d736f6ffa0332ab152498Kevin Jin rootView.destroyDrawingCache(); 93e2660726a43b1a68729d736f6ffa0332ab152498Kevin Jin rootView.buildDrawingCache(false); 946b3044b3bb260efec4b9c4cfe0fd8920841a6e7dKevin Jin screenshot = Bitmap.createBitmap(rootView.getDrawingCache()); 95e2660726a43b1a68729d736f6ffa0332ab152498Kevin Jin rootView.destroyDrawingCache(); 96e2660726a43b1a68729d736f6ffa0332ab152498Kevin Jin } 97e2660726a43b1a68729d736f6ffa0332ab152498Kevin Jin } 98e2660726a43b1a68729d736f6ffa0332ab152498Kevin Jin 99e2660726a43b1a68729d736f6ffa0332ab152498Kevin Jin @Override 100e2660726a43b1a68729d736f6ffa0332ab152498Kevin Jin protected Bitmap takeScreenshot() { 101c91cb19438c6ef8ecd794664bf1f879725866bb9Kevin Jin ScreenshotRunnable screenshotRunnable = new ScreenshotRunnable(findRootView()); 10221a0001e2426644dd68e6140b5873ebaeafcc3dcKevin Jin instrumentation.runOnMainSync(screenshotRunnable); 103e2660726a43b1a68729d736f6ffa0332ab152498Kevin Jin return screenshotRunnable.screenshot; 104e2660726a43b1a68729d736f6ffa0332ab152498Kevin Jin } 105cddda72410c992a12db61cef26713b498e31fea4Thanh Le} 106