Loading core/java/com/android/internal/os/BinderInternal.java +44 −21 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) { } } /** Loading @@ -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); } /** Loading @@ -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)); } } } Loading core/jni/android_util_Binder.cpp +24 −5 Original line number Diff line number Diff line Loading @@ -88,6 +88,7 @@ static struct binderinternal_offsets_t jclass mClass; jmethodID mForceGc; jmethodID mProxyLimitCallback; jmethodID mProxyWarningCallback; } gBinderInternalOffsets; Loading Loading @@ -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, Loading @@ -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) { Loading @@ -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); } // ---------------------------------------------------------------------------- Loading @@ -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"; Loading @@ -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); Loading @@ -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, Loading core/tests/coretests/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -134,6 +134,8 @@ android_test { ":BinderDeathRecipientHelperApp1", ":BinderDeathRecipientHelperApp2", ":com.android.cts.helpers.aosp", ":BinderProxyCountingTestApp", ":BinderProxyCountingTestService", ], } Loading core/tests/coretests/AndroidTest.xml +2 −0 Original line number Diff line number Diff line Loading @@ -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"> Loading core/tests/coretests/BinderProxyCountingTestApp/AndroidManifest.xml +3 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
core/java/com/android/internal/os/BinderInternal.java +44 −21 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) { } } /** Loading @@ -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); } /** Loading @@ -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)); } } } Loading
core/jni/android_util_Binder.cpp +24 −5 Original line number Diff line number Diff line Loading @@ -88,6 +88,7 @@ static struct binderinternal_offsets_t jclass mClass; jmethodID mForceGc; jmethodID mProxyLimitCallback; jmethodID mProxyWarningCallback; } gBinderInternalOffsets; Loading Loading @@ -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, Loading @@ -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) { Loading @@ -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); } // ---------------------------------------------------------------------------- Loading @@ -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"; Loading @@ -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); Loading @@ -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, Loading
core/tests/coretests/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -134,6 +134,8 @@ android_test { ":BinderDeathRecipientHelperApp1", ":BinderDeathRecipientHelperApp2", ":com.android.cts.helpers.aosp", ":BinderProxyCountingTestApp", ":BinderProxyCountingTestService", ], } Loading
core/tests/coretests/AndroidTest.xml +2 −0 Original line number Diff line number Diff line Loading @@ -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"> Loading
core/tests/coretests/BinderProxyCountingTestApp/AndroidManifest.xml +3 −0 Original line number Diff line number Diff line Loading @@ -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