Loading core/java/android/os/Binder.java +7 −0 Original line number Diff line number Diff line Loading @@ -122,6 +122,13 @@ public class Binder implements IBinder { private static native long getNativeFinalizer(); /** * Returns the TID (task ID) for the current thread. Same as {@link Thread#getNativeTid()} * * @hide */ public static native int getNativeTid(); // Use a Holder to allow static initialization of Binder in the boot image, and // possibly to avoid some initialization ordering issues. private static class NoImagePreloadHolder { Loading core/java/com/android/internal/os/BinderCallsStats.java +40 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.os.UserHandle; import android.text.format.DateFormat; import android.util.ArrayMap; import android.util.ArraySet; import android.util.IntArray; import android.util.Pair; import android.util.Slog; import android.util.SparseArray; Loading Loading @@ -126,6 +127,11 @@ public class BinderCallsStats implements BinderInternal.Observer { } }; private final Object mNativeTidsLock = new Object(); // @GuardedBy("mNativeTidsLock") // Cannot mark it as "GuardedBy" because it's read // directly, as a volatile field. private volatile IntArray mNativeTids = new IntArray(0); /** Injector for {@link BinderCallsStats}. */ public static class Injector { public Random getRandomGenerator() { Loading Loading @@ -175,6 +181,8 @@ public class BinderCallsStats implements BinderInternal.Observer { return null; } noteNativeThreadId(); final CallSession s = obtainCallSession(); s.binderClass = binder.getClass(); s.transactionCode = code; Loading Loading @@ -312,6 +320,27 @@ public class BinderCallsStats implements BinderInternal.Observer { } } private void noteNativeThreadId() { final int tid = getNativeTid(); int index = mNativeTids.binarySearch(tid); if (index >= 0) { return; } // Use the copy-on-write approach. The changes occur exceedingly infrequently, so // this code path is exercised just a few times per boot synchronized (mNativeTidsLock) { IntArray nativeTids = mNativeTids; index = nativeTids.binarySearch(tid); if (index < 0) { IntArray copyOnWriteArray = new IntArray(nativeTids.size() + 1); copyOnWriteArray.addAll(nativeTids); copyOnWriteArray.add(-index - 1, tid); mNativeTids = copyOnWriteArray; } } } /** * This method is expensive to call. */ Loading Loading @@ -505,6 +534,17 @@ public class BinderCallsStats implements BinderInternal.Observer { return Binder.getCallingUid(); } protected int getNativeTid() { return Binder.getNativeTid(); } /** * Returns known Linux TIDs for threads taking incoming binder calls. */ public int[] getNativeTids() { return mNativeTids.toArray(); } protected long getElapsedRealtimeMicro() { return SystemClock.elapsedRealtimeNanos() / 1000; } Loading core/jni/android_util_Binder.cpp +6 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ #include <unistd.h> #include <android-base/stringprintf.h> #include <android-base/threads.h> #include <binder/BpBinder.h> #include <binder/IInterface.h> #include <binder/IPCThreadState.h> Loading Loading @@ -1047,6 +1048,10 @@ static void android_os_Binder_setExtension(JNIEnv* env, jobject obj, jobject ext jbh->setExtension(extension); } JNIEXPORT jint JNICALL android_os_Binder_getNativeTid(JNIEnv* env, jobject clazz) { return (jint)android::base::GetThreadId(); } // ---------------------------------------------------------------------------- static const JNINativeMethod gBinderMethods[] = { Loading Loading @@ -1078,6 +1083,7 @@ static const JNINativeMethod gBinderMethods[] = { { "blockUntilThreadAvailable", "()V", (void*)android_os_Binder_blockUntilThreadAvailable }, { "getExtension", "()Landroid/os/IBinder;", (void*)android_os_Binder_getExtension }, { "setExtension", "(Landroid/os/IBinder;)V", (void*)android_os_Binder_setExtension }, { "getNativeTid", "()I", (void*)android_os_Binder_getNativeTid }, }; const char* const kBinderPathName = "android/os/Binder"; Loading core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java +38 −1 Original line number Diff line number Diff line Loading @@ -807,6 +807,38 @@ public class BinderCallsStatsTest { } } @Test public void testNativeTids() { TestBinderCallsStats bcs = new TestBinderCallsStats(); Binder binder = new Binder(); bcs.nativeTid = 3; CallSession callSession = bcs.callStarted(binder, 1, WORKSOURCE_UID); bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID); bcs.nativeTid = 1; callSession = bcs.callStarted(binder, 1, WORKSOURCE_UID); bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID); bcs.nativeTid = 1; callSession = bcs.callStarted(binder, 1, WORKSOURCE_UID); bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID); bcs.nativeTid = 2; callSession = bcs.callStarted(binder, 1, WORKSOURCE_UID); bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID); int[] tids = bcs.getNativeTids(); assertEquals(3, tids.length); assertEquals(1, tids[0]); assertEquals(2, tids[1]); assertEquals(3, tids[2]); } private static class TestHandler extends Handler { ArrayList<Runnable> mRunnables = new ArrayList<>(); Loading @@ -825,6 +857,7 @@ public class BinderCallsStatsTest { public int callingUid = CALLING_UID; public long time = 1234; public long elapsedTime = 0; public int nativeTid; TestBinderCallsStats() { this(mDeviceState); Loading Loading @@ -874,6 +907,10 @@ public class BinderCallsStatsTest { protected void setCallingUid(int uid) { callingUid = uid; } } @Override protected int getNativeTid() { return nativeTid; } } } Loading
core/java/android/os/Binder.java +7 −0 Original line number Diff line number Diff line Loading @@ -122,6 +122,13 @@ public class Binder implements IBinder { private static native long getNativeFinalizer(); /** * Returns the TID (task ID) for the current thread. Same as {@link Thread#getNativeTid()} * * @hide */ public static native int getNativeTid(); // Use a Holder to allow static initialization of Binder in the boot image, and // possibly to avoid some initialization ordering issues. private static class NoImagePreloadHolder { Loading
core/java/com/android/internal/os/BinderCallsStats.java +40 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.os.UserHandle; import android.text.format.DateFormat; import android.util.ArrayMap; import android.util.ArraySet; import android.util.IntArray; import android.util.Pair; import android.util.Slog; import android.util.SparseArray; Loading Loading @@ -126,6 +127,11 @@ public class BinderCallsStats implements BinderInternal.Observer { } }; private final Object mNativeTidsLock = new Object(); // @GuardedBy("mNativeTidsLock") // Cannot mark it as "GuardedBy" because it's read // directly, as a volatile field. private volatile IntArray mNativeTids = new IntArray(0); /** Injector for {@link BinderCallsStats}. */ public static class Injector { public Random getRandomGenerator() { Loading Loading @@ -175,6 +181,8 @@ public class BinderCallsStats implements BinderInternal.Observer { return null; } noteNativeThreadId(); final CallSession s = obtainCallSession(); s.binderClass = binder.getClass(); s.transactionCode = code; Loading Loading @@ -312,6 +320,27 @@ public class BinderCallsStats implements BinderInternal.Observer { } } private void noteNativeThreadId() { final int tid = getNativeTid(); int index = mNativeTids.binarySearch(tid); if (index >= 0) { return; } // Use the copy-on-write approach. The changes occur exceedingly infrequently, so // this code path is exercised just a few times per boot synchronized (mNativeTidsLock) { IntArray nativeTids = mNativeTids; index = nativeTids.binarySearch(tid); if (index < 0) { IntArray copyOnWriteArray = new IntArray(nativeTids.size() + 1); copyOnWriteArray.addAll(nativeTids); copyOnWriteArray.add(-index - 1, tid); mNativeTids = copyOnWriteArray; } } } /** * This method is expensive to call. */ Loading Loading @@ -505,6 +534,17 @@ public class BinderCallsStats implements BinderInternal.Observer { return Binder.getCallingUid(); } protected int getNativeTid() { return Binder.getNativeTid(); } /** * Returns known Linux TIDs for threads taking incoming binder calls. */ public int[] getNativeTids() { return mNativeTids.toArray(); } protected long getElapsedRealtimeMicro() { return SystemClock.elapsedRealtimeNanos() / 1000; } Loading
core/jni/android_util_Binder.cpp +6 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ #include <unistd.h> #include <android-base/stringprintf.h> #include <android-base/threads.h> #include <binder/BpBinder.h> #include <binder/IInterface.h> #include <binder/IPCThreadState.h> Loading Loading @@ -1047,6 +1048,10 @@ static void android_os_Binder_setExtension(JNIEnv* env, jobject obj, jobject ext jbh->setExtension(extension); } JNIEXPORT jint JNICALL android_os_Binder_getNativeTid(JNIEnv* env, jobject clazz) { return (jint)android::base::GetThreadId(); } // ---------------------------------------------------------------------------- static const JNINativeMethod gBinderMethods[] = { Loading Loading @@ -1078,6 +1083,7 @@ static const JNINativeMethod gBinderMethods[] = { { "blockUntilThreadAvailable", "()V", (void*)android_os_Binder_blockUntilThreadAvailable }, { "getExtension", "()Landroid/os/IBinder;", (void*)android_os_Binder_getExtension }, { "setExtension", "(Landroid/os/IBinder;)V", (void*)android_os_Binder_setExtension }, { "getNativeTid", "()I", (void*)android_os_Binder_getNativeTid }, }; const char* const kBinderPathName = "android/os/Binder"; Loading
core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java +38 −1 Original line number Diff line number Diff line Loading @@ -807,6 +807,38 @@ public class BinderCallsStatsTest { } } @Test public void testNativeTids() { TestBinderCallsStats bcs = new TestBinderCallsStats(); Binder binder = new Binder(); bcs.nativeTid = 3; CallSession callSession = bcs.callStarted(binder, 1, WORKSOURCE_UID); bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID); bcs.nativeTid = 1; callSession = bcs.callStarted(binder, 1, WORKSOURCE_UID); bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID); bcs.nativeTid = 1; callSession = bcs.callStarted(binder, 1, WORKSOURCE_UID); bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID); bcs.nativeTid = 2; callSession = bcs.callStarted(binder, 1, WORKSOURCE_UID); bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID); int[] tids = bcs.getNativeTids(); assertEquals(3, tids.length); assertEquals(1, tids[0]); assertEquals(2, tids[1]); assertEquals(3, tids[2]); } private static class TestHandler extends Handler { ArrayList<Runnable> mRunnables = new ArrayList<>(); Loading @@ -825,6 +857,7 @@ public class BinderCallsStatsTest { public int callingUid = CALLING_UID; public long time = 1234; public long elapsedTime = 0; public int nativeTid; TestBinderCallsStats() { this(mDeviceState); Loading Loading @@ -874,6 +907,10 @@ public class BinderCallsStatsTest { protected void setCallingUid(int uid) { callingUid = uid; } } @Override protected int getNativeTid() { return nativeTid; } } }