| /* |
| * Copyright (C) 2013 DroidDriver committers |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package io.appium.droiddriver.instrumentation; |
| |
| import android.os.Build; |
| import android.view.View; |
| |
| import java.lang.reflect.Field; |
| import java.lang.reflect.InvocationTargetException; |
| import java.lang.reflect.Method; |
| import java.util.Arrays; |
| import java.util.List; |
| |
| import io.appium.droiddriver.exceptions.DroidDriverException; |
| |
| /** |
| * Class to find the root view. |
| */ |
| public class RootFinder { |
| |
| private static final String VIEW_FIELD_NAME = "mViews"; |
| private static final Field viewsField; |
| private static final Object windowManagerObj; |
| |
| static { |
| String windowManagerClassName = |
| Build.VERSION.SDK_INT >= 17 ? "android.view.WindowManagerGlobal" |
| : "android.view.WindowManagerImpl"; |
| String instanceMethod = Build.VERSION.SDK_INT >= 17 ? "getInstance" : "getDefault"; |
| try { |
| Class<?> clazz = Class.forName(windowManagerClassName); |
| Method getMethod = clazz.getMethod(instanceMethod); |
| windowManagerObj = getMethod.invoke(null); |
| viewsField = clazz.getDeclaredField(VIEW_FIELD_NAME); |
| viewsField.setAccessible(true); |
| } catch (InvocationTargetException ite) { |
| throw new DroidDriverException(String.format("could not invoke: %s on %s", instanceMethod, |
| windowManagerClassName), ite.getCause()); |
| } catch (ClassNotFoundException cnfe) { |
| throw new DroidDriverException(String.format("could not find class: %s", |
| windowManagerClassName), cnfe); |
| } catch (NoSuchFieldException nsfe) { |
| throw new DroidDriverException(String.format("could not find field: %s on %s", |
| VIEW_FIELD_NAME, windowManagerClassName), nsfe); |
| } catch (NoSuchMethodException nsme) { |
| throw new DroidDriverException(String.format("could not find method: %s on %s", |
| instanceMethod, windowManagerClassName), nsme); |
| } catch (RuntimeException re) { |
| throw new DroidDriverException(String.format( |
| "reflective setup failed using obj: %s method: %s field: %s", windowManagerClassName, |
| instanceMethod, VIEW_FIELD_NAME), re); |
| } catch (IllegalAccessException iae) { |
| throw new DroidDriverException(String.format( |
| "reflective setup failed using obj: %s method: %s field: %s", windowManagerClassName, |
| instanceMethod, VIEW_FIELD_NAME), iae); |
| } |
| } |
| |
| /** |
| * @return a list of {@link View}s. |
| */ |
| @SuppressWarnings("unchecked") |
| public static List<View> getRootViews() { |
| List<View> views = null; |
| |
| try { |
| if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { |
| views = (List<View>) viewsField.get(windowManagerObj); |
| } else { |
| views = Arrays.asList((View[]) viewsField.get(windowManagerObj)); |
| } |
| return views; |
| } catch (RuntimeException re) { |
| throw new DroidDriverException(String.format("Reflective access to %s on %s failed.", |
| viewsField, windowManagerObj), re); |
| } catch (IllegalAccessException iae) { |
| throw new DroidDriverException(String.format("Reflective access to %s on %s failed.", |
| viewsField, windowManagerObj), iae); |
| } |
| } |
| } |