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 174b31201b5a2dbf8036da5a8d089a68a39cc1dc44Kevin Jinpackage io.appium.droiddriver.instrumentation; 18cddda72410c992a12db61cef26713b498e31fea4Thanh Le 19cddda72410c992a12db61cef26713b498e31fea4Thanh Leimport android.os.Build; 20cddda72410c992a12db61cef26713b498e31fea4Thanh Leimport android.view.View; 21cddda72410c992a12db61cef26713b498e31fea4Thanh Le 22cddda72410c992a12db61cef26713b498e31fea4Thanh Leimport java.lang.reflect.Field; 23cddda72410c992a12db61cef26713b498e31fea4Thanh Leimport java.lang.reflect.InvocationTargetException; 24cddda72410c992a12db61cef26713b498e31fea4Thanh Leimport java.lang.reflect.Method; 25b8fc7911443ee5666ba46e016f11284f8ffa3662Karl Blassimport java.util.Arrays; 26b8fc7911443ee5666ba46e016f11284f8ffa3662Karl Blassimport java.util.List; 27b8fc7911443ee5666ba46e016f11284f8ffa3662Karl Blass 284b31201b5a2dbf8036da5a8d089a68a39cc1dc44Kevin Jinimport io.appium.droiddriver.exceptions.DroidDriverException; 294b31201b5a2dbf8036da5a8d089a68a39cc1dc44Kevin Jin 30cddda72410c992a12db61cef26713b498e31fea4Thanh Le/** 31cddda72410c992a12db61cef26713b498e31fea4Thanh Le * Class to find the root view. 32cddda72410c992a12db61cef26713b498e31fea4Thanh Le */ 33cddda72410c992a12db61cef26713b498e31fea4Thanh Lepublic class RootFinder { 34cddda72410c992a12db61cef26713b498e31fea4Thanh Le 35cddda72410c992a12db61cef26713b498e31fea4Thanh Le private static final String VIEW_FIELD_NAME = "mViews"; 36cddda72410c992a12db61cef26713b498e31fea4Thanh Le private static final Field viewsField; 37cddda72410c992a12db61cef26713b498e31fea4Thanh Le private static final Object windowManagerObj; 38cddda72410c992a12db61cef26713b498e31fea4Thanh Le 39cddda72410c992a12db61cef26713b498e31fea4Thanh Le static { 4045828d52e6a2d9694eb507b5cafd3b6fcae9c33cKevin Jin String windowManagerClassName = 4145828d52e6a2d9694eb507b5cafd3b6fcae9c33cKevin Jin Build.VERSION.SDK_INT >= 17 ? "android.view.WindowManagerGlobal" 4245828d52e6a2d9694eb507b5cafd3b6fcae9c33cKevin Jin : "android.view.WindowManagerImpl"; 43cddda72410c992a12db61cef26713b498e31fea4Thanh Le String instanceMethod = Build.VERSION.SDK_INT >= 17 ? "getInstance" : "getDefault"; 44cddda72410c992a12db61cef26713b498e31fea4Thanh Le try { 45cddda72410c992a12db61cef26713b498e31fea4Thanh Le Class<?> clazz = Class.forName(windowManagerClassName); 46cddda72410c992a12db61cef26713b498e31fea4Thanh Le Method getMethod = clazz.getMethod(instanceMethod); 47cddda72410c992a12db61cef26713b498e31fea4Thanh Le windowManagerObj = getMethod.invoke(null); 48cddda72410c992a12db61cef26713b498e31fea4Thanh Le viewsField = clazz.getDeclaredField(VIEW_FIELD_NAME); 49cddda72410c992a12db61cef26713b498e31fea4Thanh Le viewsField.setAccessible(true); 50cddda72410c992a12db61cef26713b498e31fea4Thanh Le } catch (InvocationTargetException ite) { 51cddda72410c992a12db61cef26713b498e31fea4Thanh Le throw new DroidDriverException(String.format("could not invoke: %s on %s", instanceMethod, 52cddda72410c992a12db61cef26713b498e31fea4Thanh Le windowManagerClassName), ite.getCause()); 53cddda72410c992a12db61cef26713b498e31fea4Thanh Le } catch (ClassNotFoundException cnfe) { 5445828d52e6a2d9694eb507b5cafd3b6fcae9c33cKevin Jin throw new DroidDriverException(String.format("could not find class: %s", 5545828d52e6a2d9694eb507b5cafd3b6fcae9c33cKevin Jin windowManagerClassName), cnfe); 56cddda72410c992a12db61cef26713b498e31fea4Thanh Le } catch (NoSuchFieldException nsfe) { 57cddda72410c992a12db61cef26713b498e31fea4Thanh Le throw new DroidDriverException(String.format("could not find field: %s on %s", 58cddda72410c992a12db61cef26713b498e31fea4Thanh Le VIEW_FIELD_NAME, windowManagerClassName), nsfe); 59cddda72410c992a12db61cef26713b498e31fea4Thanh Le } catch (NoSuchMethodException nsme) { 60cddda72410c992a12db61cef26713b498e31fea4Thanh Le throw new DroidDriverException(String.format("could not find method: %s on %s", 61cddda72410c992a12db61cef26713b498e31fea4Thanh Le instanceMethod, windowManagerClassName), nsme); 62cddda72410c992a12db61cef26713b498e31fea4Thanh Le } catch (RuntimeException re) { 6345828d52e6a2d9694eb507b5cafd3b6fcae9c33cKevin Jin throw new DroidDriverException(String.format( 6445828d52e6a2d9694eb507b5cafd3b6fcae9c33cKevin Jin "reflective setup failed using obj: %s method: %s field: %s", windowManagerClassName, 6545828d52e6a2d9694eb507b5cafd3b6fcae9c33cKevin Jin instanceMethod, VIEW_FIELD_NAME), re); 66cddda72410c992a12db61cef26713b498e31fea4Thanh Le } catch (IllegalAccessException iae) { 6745828d52e6a2d9694eb507b5cafd3b6fcae9c33cKevin Jin throw new DroidDriverException(String.format( 6845828d52e6a2d9694eb507b5cafd3b6fcae9c33cKevin Jin "reflective setup failed using obj: %s method: %s field: %s", windowManagerClassName, 6945828d52e6a2d9694eb507b5cafd3b6fcae9c33cKevin Jin instanceMethod, VIEW_FIELD_NAME), iae); 70cddda72410c992a12db61cef26713b498e31fea4Thanh Le } 71cddda72410c992a12db61cef26713b498e31fea4Thanh Le } 72cddda72410c992a12db61cef26713b498e31fea4Thanh Le 73cddda72410c992a12db61cef26713b498e31fea4Thanh Le /** 74cddda72410c992a12db61cef26713b498e31fea4Thanh Le * @return a list of {@link View}s. 75cddda72410c992a12db61cef26713b498e31fea4Thanh Le */ 76b8fc7911443ee5666ba46e016f11284f8ffa3662Karl Blass @SuppressWarnings("unchecked") 77b8fc7911443ee5666ba46e016f11284f8ffa3662Karl Blass public static List<View> getRootViews() { 78b8fc7911443ee5666ba46e016f11284f8ffa3662Karl Blass List<View> views = null; 79cddda72410c992a12db61cef26713b498e31fea4Thanh Le 80cddda72410c992a12db61cef26713b498e31fea4Thanh Le try { 81b8fc7911443ee5666ba46e016f11284f8ffa3662Karl Blass if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 82b8fc7911443ee5666ba46e016f11284f8ffa3662Karl Blass views = (List<View>) viewsField.get(windowManagerObj); 83b8fc7911443ee5666ba46e016f11284f8ffa3662Karl Blass } else { 84b8fc7911443ee5666ba46e016f11284f8ffa3662Karl Blass views = Arrays.asList((View[]) viewsField.get(windowManagerObj)); 85b8fc7911443ee5666ba46e016f11284f8ffa3662Karl Blass } 86cddda72410c992a12db61cef26713b498e31fea4Thanh Le return views; 87cddda72410c992a12db61cef26713b498e31fea4Thanh Le } catch (RuntimeException re) { 88cddda72410c992a12db61cef26713b498e31fea4Thanh Le throw new DroidDriverException(String.format("Reflective access to %s on %s failed.", 89cddda72410c992a12db61cef26713b498e31fea4Thanh Le viewsField, windowManagerObj), re); 90cddda72410c992a12db61cef26713b498e31fea4Thanh Le } catch (IllegalAccessException iae) { 91cddda72410c992a12db61cef26713b498e31fea4Thanh Le throw new DroidDriverException(String.format("Reflective access to %s on %s failed.", 92cddda72410c992a12db61cef26713b498e31fea4Thanh Le viewsField, windowManagerObj), iae); 93cddda72410c992a12db61cef26713b498e31fea4Thanh Le } 94cddda72410c992a12db61cef26713b498e31fea4Thanh Le } 95cddda72410c992a12db61cef26713b498e31fea4Thanh Le} 96