Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6dbeda2c authored by Brandon Maxwell's avatar Brandon Maxwell Committed by Android (Google) Code Review
Browse files

Merge "Added method to check if methods are available at runtime" into ub-contactsdialer-b-dev

parents 471b4fc9 6edc0e6b
Loading
Loading
Loading
Loading
+33 −3
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ package com.android.contacts.common.compat;

import android.os.Build;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;

import com.android.contacts.common.model.CPOWrapper;
@@ -116,10 +117,10 @@ public final class CompatUtils {
     *
     * @param className the name of the class to look for.
     * @return {@code true} if the given class is available, {@code false} otherwise or if className
     *    is null.
     *    is empty.
     */
    public static boolean isClassAvailable(@Nullable String className) {
        if (className == null) {
        if (TextUtils.isEmpty(className)) {
            return false;
        }
        try {
@@ -128,7 +129,36 @@ public final class CompatUtils {
        } catch (ClassNotFoundException e) {
            return false;
        } catch (Throwable t) {
            Log.e(TAG, "Unexpected exception when checking if class exists at runtime", t);
            Log.e(TAG, "Unexpected exception when checking if class:" + className + " exists at "
                    + "runtime", t);
            return false;
        }
    }

    /**
     * Determines if the given class's method is available to call. Can be used to check if system
     * apis exist at runtime.
     *
     * @param className the name of the class to look for
     * @param methodName the name of the method to look for
     * @param parameterTypes the needed parameter types for the method to look for
     * @return {@code true} if the given class is available, {@code false} otherwise or if className
     *    or methodName are empty.
     */
    public static boolean isMethodAvailable(@Nullable String className, @Nullable String methodName,
            Class<?>... parameterTypes) {
        if (TextUtils.isEmpty(className) || TextUtils.isEmpty(methodName)) {
            return false;
        }

        try {
            Class.forName(className).getMethod(methodName, parameterTypes);
            return true;
        } catch (ClassNotFoundException | NoSuchMethodException e) {
            return false;
        } catch (Throwable t) {
            Log.e(TAG, "Unexpected exception when checking if method: " + className + "#"
                    + methodName + " exists at runtime", t);
            return false;
        }
    }
+68 −4
Original line number Diff line number Diff line
@@ -20,11 +20,75 @@ import android.test.AndroidTestCase;

public class CompatUtilsTest extends AndroidTestCase {

    public void testClassAvailable() {
        assertTrue(CompatUtils.isClassAvailable(CompatUtils.class.getName()));
    public void testIsClassAvailable_NullClassName() {
        assertFalse(CompatUtils.isClassAvailable(null));
    }

    public void testClassNotAvailable() {
        assertFalse(CompatUtils.isClassAvailable("com.android.contacts.common.NonexistantClass"));
    public void testIsClassAvailable_EmptyClassName() {
        assertFalse(CompatUtils.isClassAvailable(""));
    }

    public void testIsClassAvailable_NonexistentClass() {
        assertFalse(CompatUtils.isClassAvailable("com.android.contacts.common.NonexistentClass"));
    }

    public void testIsClassAvailable() {
        assertTrue(CompatUtils.isClassAvailable(BaseClass.class.getName()));
    }

    public void testIsMethodAvailable_NullClassName() {
        assertFalse(CompatUtils.isMethodAvailable(null, "methodName"));
    }

    public void testIsMethodAvailable_EmptyClassName() {
        assertFalse(CompatUtils.isMethodAvailable("", "methodName"));
    }

    public void testIsMethodAvailable_NullMethodName() {
        assertFalse(CompatUtils.isMethodAvailable("className", null));
    }

    public void testIsMethodAvailable_EmptyMethodName() {
        assertFalse(CompatUtils.isMethodAvailable("className", ""));
    }

    public void testIsMethodAvailable_NonexistentClass() {
        assertFalse(CompatUtils.isMethodAvailable("com.android.contacts.common.NonexistentClass",
                ""));
    }

    public void testIsMethodAvailable_NonexistentMethod() {
        assertFalse(CompatUtils.isMethodAvailable(BaseClass.class.getName(), "derivedMethod"));
    }

    public void testIsMethodAvailable() {
        assertTrue(CompatUtils.isMethodAvailable(BaseClass.class.getName(), "baseMethod"));
    }

    public void testIsMethodAvailable_InheritedMethod() {
        assertTrue(CompatUtils.isMethodAvailable(DerivedClass.class.getName(), "baseMethod"));
    }

    public void testIsMethodAvailable_OverloadedMethod() {
        assertTrue(CompatUtils.isMethodAvailable(DerivedClass.class.getName(), "overloadedMethod"));
        assertTrue(CompatUtils.isMethodAvailable(DerivedClass.class.getName(), "overloadedMethod",
                Integer.TYPE));
    }

    public void testIsMethodAvailable_NonexistentOverload() {
        assertFalse(CompatUtils.isMethodAvailable(DerivedClass.class.getName(), "overloadedMethod",
                Boolean.TYPE));
    }

    private class BaseClass {
        public void baseMethod() {}
    }

    private class DerivedClass extends BaseClass {
        public void derivedMethod() {}

        public void overloadedMethod() {}

        public void overloadedMethod(int i) {}
    }
}