Collect native TIDs for binder threads
This information will be used for attribution of CPU usage to work source UIDs. Bug: 158232997 Test: atest FrameworksCoreTests:com.android.internal.os.BinderCallsStatsTest Change-Id: Ic9fcc1d62515dd11a1fbade80264412615014919
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
@@ -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() {
|
||||
@@ -175,6 +181,8 @@ public class BinderCallsStats implements BinderInternal.Observer {
|
||||
return null;
|
||||
}
|
||||
|
||||
noteNativeThreadId();
|
||||
|
||||
final CallSession s = obtainCallSession();
|
||||
s.binderClass = binder.getClass();
|
||||
s.transactionCode = code;
|
||||
@@ -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.
|
||||
*/
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
@@ -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[] = {
|
||||
@@ -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";
|
||||
|
||||
@@ -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<>();
|
||||
|
||||
@@ -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);
|
||||
@@ -874,6 +907,10 @@ public class BinderCallsStatsTest {
|
||||
protected void setCallingUid(int uid) {
|
||||
callingUid = uid;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getNativeTid() {
|
||||
return nativeTid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user