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.instrumentation; 18 19import android.os.Build; 20import android.view.View; 21 22import com.google.android.droiddriver.exceptions.DroidDriverException; 23 24import java.lang.reflect.Field; 25import java.lang.reflect.InvocationTargetException; 26import java.lang.reflect.Method; 27 28/** 29 * Class to find the root view. 30 */ 31public class RootFinder { 32 33 private static final String VIEW_FIELD_NAME = "mViews"; 34 private static final Field viewsField; 35 private static final Object windowManagerObj; 36 37 static { 38 String windowManagerClassName = 39 Build.VERSION.SDK_INT >= 17 ? "android.view.WindowManagerGlobal" 40 : "android.view.WindowManagerImpl"; 41 String instanceMethod = Build.VERSION.SDK_INT >= 17 ? "getInstance" : "getDefault"; 42 try { 43 Class<?> clazz = Class.forName(windowManagerClassName); 44 Method getMethod = clazz.getMethod(instanceMethod); 45 windowManagerObj = getMethod.invoke(null); 46 viewsField = clazz.getDeclaredField(VIEW_FIELD_NAME); 47 viewsField.setAccessible(true); 48 } catch (InvocationTargetException ite) { 49 throw new DroidDriverException(String.format("could not invoke: %s on %s", instanceMethod, 50 windowManagerClassName), ite.getCause()); 51 } catch (ClassNotFoundException cnfe) { 52 throw new DroidDriverException(String.format("could not find class: %s", 53 windowManagerClassName), cnfe); 54 } catch (NoSuchFieldException nsfe) { 55 throw new DroidDriverException(String.format("could not find field: %s on %s", 56 VIEW_FIELD_NAME, windowManagerClassName), nsfe); 57 } catch (NoSuchMethodException nsme) { 58 throw new DroidDriverException(String.format("could not find method: %s on %s", 59 instanceMethod, windowManagerClassName), nsme); 60 } catch (RuntimeException re) { 61 throw new DroidDriverException(String.format( 62 "reflective setup failed using obj: %s method: %s field: %s", windowManagerClassName, 63 instanceMethod, VIEW_FIELD_NAME), re); 64 } catch (IllegalAccessException iae) { 65 throw new DroidDriverException(String.format( 66 "reflective setup failed using obj: %s method: %s field: %s", windowManagerClassName, 67 instanceMethod, VIEW_FIELD_NAME), iae); 68 } 69 } 70 71 /** 72 * @return a list of {@link View}s. 73 */ 74 public static View[] getRootViews() { 75 View[] views = null; 76 77 try { 78 views = (View[]) viewsField.get(windowManagerObj); 79 return views; 80 } catch (RuntimeException re) { 81 throw new DroidDriverException(String.format("Reflective access to %s on %s failed.", 82 viewsField, windowManagerObj), re); 83 } catch (IllegalAccessException iae) { 84 throw new DroidDriverException(String.format("Reflective access to %s on %s failed.", 85 viewsField, windowManagerObj), iae); 86 } 87 } 88} 89