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

Commit ad2da357 authored by Jing Ji's avatar Jing Ji Committed by Gerrit Code Review
Browse files

Merge changes from topic "bug_298263955_proxy_warning" into main

* changes:
  Log the excessive incoming binder proxies into statsd
  Add a feature flag to log excessive incoming binder proxies in statsd
parents 11514e74 9a856d32
Loading
Loading
Loading
Loading
+44 −21
Original line number Original line Diff line number Diff line
@@ -45,8 +45,8 @@ public class BinderInternal {
    static ArrayList<Runnable> sGcWatchers = new ArrayList<>();
    static ArrayList<Runnable> sGcWatchers = new ArrayList<>();
    static Runnable[] sTmpWatchers = new Runnable[1];
    static Runnable[] sTmpWatchers = new Runnable[1];
    static long sLastGcTime;
    static long sLastGcTime;
    static final BinderProxyLimitListenerDelegate sBinderProxyLimitListenerDelegate =
    static final BinderProxyCountEventListenerDelegate sBinderProxyCountEventListenerDelegate =
            new BinderProxyLimitListenerDelegate();
            new BinderProxyCountEventListenerDelegate();


    static final class GcWatcher {
    static final class GcWatcher {
        @Override
        @Override
@@ -226,15 +226,24 @@ public class BinderInternal {
     * @param low   The threshold a binder count must drop below before the callback
     * @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
     *              can be called again. (This is to avoid many repeated calls to the
     *              callback in a brief period of time)
     *              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
     * 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
     * be called with the uid of the app causing too many Binder Proxies
     */
     */
    public interface BinderProxyLimitListener {
    public interface BinderProxyCountEventListener {
        public void onLimitReached(int uid);
        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
     * @param uid The uid of the bad behaving app sending too many binders
     */
     */
    public static void binderProxyLimitCallbackFromNative(int uid) {
    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;
     * @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) {
            @NonNull Handler handler) {
        Preconditions.checkNotNull(handler,
        Preconditions.checkNotNull(handler,
                "Must provide NonNull Handler to setBinderProxyCountCallback when setting "
                "Must provide NonNull Handler to setBinderProxyCountCallback when setting "
                        + "BinderProxyLimitListener");
                        + "BinderProxyCountEventListener");
        sBinderProxyLimitListenerDelegate.setListener(listener, handler);
        sBinderProxyCountEventListenerDelegate.setListener(listener, handler);
    }
    }


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


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


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


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

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


} gBinderInternalOffsets;
} gBinderInternalOffsets;


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


static void android_os_BinderInternal_proxyLimitcallback(int uid)
static void android_os_BinderInternal_proxyLimitCallback(int uid)
{
{
    JNIEnv *env = AndroidRuntime::getJNIEnv();
    JNIEnv *env = AndroidRuntime::getJNIEnv();
    env->CallStaticVoidMethod(gBinderInternalOffsets.mClass,
    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,
static void android_os_BinderInternal_setBinderProxyCountEnabled(JNIEnv* env, jobject clazz,
                                                                 jboolean enable)
                                                                 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,
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 },
    { "nSetBinderProxyCountEnabled", "(Z)V", (void*)android_os_BinderInternal_setBinderProxyCountEnabled },
    { "nGetBinderProxyPerUidCounts", "()Landroid/util/SparseIntArray;", (void*)android_os_BinderInternal_getBinderProxyPerUidCounts },
    { "nGetBinderProxyPerUidCounts", "()Landroid/util/SparseIntArray;", (void*)android_os_BinderInternal_getBinderProxyPerUidCounts },
    { "nGetBinderProxyCount", "(I)I", (void*)android_os_BinderInternal_getBinderProxyCount },
    { "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";
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.mClass = MakeGlobalRefOrDie(env, clazz);
    gBinderInternalOffsets.mForceGc = GetStaticMethodIDOrDie(env, clazz, "forceBinderGc", "()V");
    gBinderInternalOffsets.mForceGc = GetStaticMethodIDOrDie(env, clazz, "forceBinderGc", "()V");
    gBinderInternalOffsets.mProxyLimitCallback = GetStaticMethodIDOrDie(env, clazz, "binderProxyLimitCallbackFromNative", "(I)V");
    gBinderInternalOffsets.mProxyLimitCallback = GetStaticMethodIDOrDie(env, clazz, "binderProxyLimitCallbackFromNative", "(I)V");
    gBinderInternalOffsets.mProxyWarningCallback =
        GetStaticMethodIDOrDie(env, clazz, "binderProxyWarningCallbackFromNative", "(I)V");


    jclass SparseIntArrayClass = FindClassOrDie(env, "android/util/SparseIntArray");
    jclass SparseIntArrayClass = FindClassOrDie(env, "android/util/SparseIntArray");
    gSparseIntArrayOffsets.classObject = MakeGlobalRefOrDie(env, SparseIntArrayClass);
    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",
    gSparseIntArrayOffsets.put = GetMethodIDOrDie(env, gSparseIntArrayOffsets.classObject, "put",
                                                   "(II)V");
                                                   "(II)V");


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


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


+2 −0
Original line number Original line Diff line number Diff line
@@ -22,6 +22,8 @@
        <option name="test-file-name" value="FrameworksCoreTests.apk" />
        <option name="test-file-name" value="FrameworksCoreTests.apk" />
        <option name="test-file-name" value="BinderDeathRecipientHelperApp1.apk" />
        <option name="test-file-name" value="BinderDeathRecipientHelperApp1.apk" />
        <option name="test-file-name" value="BinderDeathRecipientHelperApp2.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>


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


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