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

Commit 617a768e authored by Jing Ji's avatar Jing Ji Committed by Android (Google) Code Review
Browse files

Merge "Log the excessive incoming binder proxies into statsd" into main

parents b79e6097 0b60166c
Loading
Loading
Loading
Loading
+44 −21
Original line number Diff line number Diff line
@@ -45,8 +45,8 @@ public class BinderInternal {
    static ArrayList<Runnable> sGcWatchers = new ArrayList<>();
    static Runnable[] sTmpWatchers = new Runnable[1];
    static long sLastGcTime;
    static final BinderProxyLimitListenerDelegate sBinderProxyLimitListenerDelegate =
            new BinderProxyLimitListenerDelegate();
    static final BinderProxyCountEventListenerDelegate sBinderProxyCountEventListenerDelegate =
            new BinderProxyCountEventListenerDelegate();

    static final class GcWatcher {
        @Override
@@ -226,15 +226,24 @@ public class BinderInternal {
     * @param low   The threshold a binder count must drop below before the callback
     *              can be called again. (This is to avoid many repeated calls to the
     *              callback in a brief period of time)
     * @param warning The threshold between {@code high} and {@code low} where if the binder count
     *                exceeds that, the warning callback would be triggered.
     */
    public static final native void nSetBinderProxyCountWatermarks(int high, int low);
    public static final native void nSetBinderProxyCountWatermarks(int high, int low, int warning);

    /**
     * Interface for callback invocation when the Binder Proxy limit is reached. onLimitReached will
     * be called with the uid of the app causing too many Binder Proxies
     */
    public interface BinderProxyLimitListener {
    public interface BinderProxyCountEventListener {
        public void onLimitReached(int uid);

        /**
         * Call when the number of binder proxies from the uid of the app reaches
         * the warning threshold.
         */
        default void onWarningThresholdReached(int uid) {
        }
    }

    /**
@@ -243,7 +252,17 @@ public class BinderInternal {
     * @param uid The uid of the bad behaving app sending too many binders
     */
    public static void binderProxyLimitCallbackFromNative(int uid) {
       sBinderProxyLimitListenerDelegate.notifyClient(uid);
        sBinderProxyCountEventListenerDelegate.notifyLimitReached(uid);
    }

    /**
     * Callback used by native code to trigger a callback in java code. The callback will be
     * triggered when too many binder proxies from a uid hits the warning limit.
     * @param uid The uid of the bad behaving app sending too many binders
     */
    @SuppressWarnings("unused")
    public static void binderProxyWarningCallbackFromNative(int uid) {
        sBinderProxyCountEventListenerDelegate.notifyWarningReached(uid);
    }

    /**
@@ -252,41 +271,45 @@ public class BinderInternal {
     * @param handler must not be null, callback will be posted through the handler;
     *
     */
    public static void setBinderProxyCountCallback(BinderProxyLimitListener listener,
    public static void setBinderProxyCountCallback(BinderProxyCountEventListener listener,
            @NonNull Handler handler) {
        Preconditions.checkNotNull(handler,
                "Must provide NonNull Handler to setBinderProxyCountCallback when setting "
                        + "BinderProxyLimitListener");
        sBinderProxyLimitListenerDelegate.setListener(listener, handler);
                        + "BinderProxyCountEventListener");
        sBinderProxyCountEventListenerDelegate.setListener(listener, handler);
    }

    /**
     * Clear the Binder Proxy callback
     */
    public static void clearBinderProxyCountCallback() {
        sBinderProxyLimitListenerDelegate.setListener(null, null);
        sBinderProxyCountEventListenerDelegate.setListener(null, null);
    }

    static private class BinderProxyLimitListenerDelegate {
        private BinderProxyLimitListener mBinderProxyLimitListener;
    private static class BinderProxyCountEventListenerDelegate {
        private BinderProxyCountEventListener mBinderProxyCountEventListener;
        private Handler mHandler;

        void setListener(BinderProxyLimitListener listener, Handler handler) {
        void setListener(BinderProxyCountEventListener listener, Handler handler) {
            synchronized (this) {
                mBinderProxyLimitListener = listener;
                mBinderProxyCountEventListener = listener;
                mHandler = handler;
            }
        }

        void notifyClient(final int uid) {
        void notifyLimitReached(final int uid) {
            synchronized (this) {
                if (mBinderProxyLimitListener != null) {
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            mBinderProxyLimitListener.onLimitReached(uid);
                if (mBinderProxyCountEventListener != null) {
                    mHandler.post(() -> mBinderProxyCountEventListener.onLimitReached(uid));
                }
            }
                    });
        }

        void notifyWarningReached(final int uid) {
            synchronized (this) {
                if (mBinderProxyCountEventListener != null) {
                    mHandler.post(() ->
                            mBinderProxyCountEventListener.onWarningThresholdReached(uid));
                }
            }
        }
+24 −5
Original line number Diff line number Diff line
@@ -88,6 +88,7 @@ static struct binderinternal_offsets_t
    jclass mClass;
    jmethodID mForceGc;
    jmethodID mProxyLimitCallback;
    jmethodID mProxyWarningCallback;

} gBinderInternalOffsets;

@@ -1240,7 +1241,7 @@ static void android_os_BinderInternal_handleGc(JNIEnv* env, jobject clazz)
    gCollectedAtRefs = gNumLocalRefsCreated + gNumDeathRefsCreated;
}

static void android_os_BinderInternal_proxyLimitcallback(int uid)
static void android_os_BinderInternal_proxyLimitCallback(int uid)
{
    JNIEnv *env = AndroidRuntime::getJNIEnv();
    env->CallStaticVoidMethod(gBinderInternalOffsets.mClass,
@@ -1254,6 +1255,20 @@ static void android_os_BinderInternal_proxyLimitcallback(int uid)
    }
}

static void android_os_BinderInternal_proxyWarningCallback(int uid)
{
    JNIEnv *env = AndroidRuntime::getJNIEnv();
    env->CallStaticVoidMethod(gBinderInternalOffsets.mClass,
                              gBinderInternalOffsets.mProxyWarningCallback,
                              uid);

    if (env->ExceptionCheck()) {
        ScopedLocalRef<jthrowable> excep(env, env->ExceptionOccurred());
        binder_report_exception(env, excep.get(),
                                "*** Uncaught exception in binderProxyWarningCallbackFromNative");
    }
}

static void android_os_BinderInternal_setBinderProxyCountEnabled(JNIEnv* env, jobject clazz,
                                                                 jboolean enable)
{
@@ -1278,9 +1293,10 @@ static jint android_os_BinderInternal_getBinderProxyCount(JNIEnv* env, jobject c
}

static void android_os_BinderInternal_setBinderProxyCountWatermarks(JNIEnv* env, jobject clazz,
                                                                    jint high, jint low)
                                                                    jint high, jint low,
                                                                    jint warning)
{
    BpBinder::setBinderProxyCountWatermarks(high, low);
    BpBinder::setBinderProxyCountWatermarks(high, low, warning);
}

// ----------------------------------------------------------------------------
@@ -1295,7 +1311,7 @@ static const JNINativeMethod gBinderInternalMethods[] = {
    { "nSetBinderProxyCountEnabled", "(Z)V", (void*)android_os_BinderInternal_setBinderProxyCountEnabled },
    { "nGetBinderProxyPerUidCounts", "()Landroid/util/SparseIntArray;", (void*)android_os_BinderInternal_getBinderProxyPerUidCounts },
    { "nGetBinderProxyCount", "(I)I", (void*)android_os_BinderInternal_getBinderProxyCount },
    { "nSetBinderProxyCountWatermarks", "(II)V", (void*)android_os_BinderInternal_setBinderProxyCountWatermarks}
    { "nSetBinderProxyCountWatermarks", "(III)V", (void*)android_os_BinderInternal_setBinderProxyCountWatermarks}
};

const char* const kBinderInternalPathName = "com/android/internal/os/BinderInternal";
@@ -1307,6 +1323,8 @@ static int int_register_android_os_BinderInternal(JNIEnv* env)
    gBinderInternalOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
    gBinderInternalOffsets.mForceGc = GetStaticMethodIDOrDie(env, clazz, "forceBinderGc", "()V");
    gBinderInternalOffsets.mProxyLimitCallback = GetStaticMethodIDOrDie(env, clazz, "binderProxyLimitCallbackFromNative", "(I)V");
    gBinderInternalOffsets.mProxyWarningCallback =
        GetStaticMethodIDOrDie(env, clazz, "binderProxyWarningCallbackFromNative", "(I)V");

    jclass SparseIntArrayClass = FindClassOrDie(env, "android/util/SparseIntArray");
    gSparseIntArrayOffsets.classObject = MakeGlobalRefOrDie(env, SparseIntArrayClass);
@@ -1315,7 +1333,8 @@ static int int_register_android_os_BinderInternal(JNIEnv* env)
    gSparseIntArrayOffsets.put = GetMethodIDOrDie(env, gSparseIntArrayOffsets.classObject, "put",
                                                   "(II)V");

    BpBinder::setLimitCallback(android_os_BinderInternal_proxyLimitcallback);
    BpBinder::setBinderProxyCountEventCallback(android_os_BinderInternal_proxyLimitCallback,
                                               android_os_BinderInternal_proxyWarningCallback);

    return RegisterMethodsOrDie(
        env, kBinderInternalPathName,
+2 −0
Original line number Diff line number Diff line
@@ -134,6 +134,8 @@ android_test {
        ":BinderDeathRecipientHelperApp1",
        ":BinderDeathRecipientHelperApp2",
        ":com.android.cts.helpers.aosp",
        ":BinderProxyCountingTestApp",
        ":BinderProxyCountingTestService",
    ],
}

+2 −0
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@
        <option name="test-file-name" value="FrameworksCoreTests.apk" />
        <option name="test-file-name" value="BinderDeathRecipientHelperApp1.apk" />
        <option name="test-file-name" value="BinderDeathRecipientHelperApp2.apk" />
        <option name="test-file-name" value="BinderProxyCountingTestApp.apk" />
        <option name="test-file-name" value="BinderProxyCountingTestService.apk" />
    </target_preparer>

    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+3 −0
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.android.frameworks.coretests.binderproxycountingtestapp">

    <queries>
        <package android:name="com.android.frameworks.coretests.binderproxycountingtestservice" />
    </queries>
    <application>
        <service android:name=".BpcTestAppCmdService"
                 android:exported="true"/>
Loading