Merge changes Ie5fa2605,Ia092e896 am: 140049bce8

Change-Id: I20fd969e2124c228506e11540bdea04676684530
This commit is contained in:
Automerger Merge Worker
2020-02-20 23:03:24 +00:00
5 changed files with 99 additions and 1 deletions

View File

@@ -53,6 +53,8 @@ public class KernelSingleUidTimeReader {
private int mReadErrorCounter; private int mReadErrorCounter;
@GuardedBy("this") @GuardedBy("this")
private boolean mSingleUidCpuTimesAvailable = true; private boolean mSingleUidCpuTimesAvailable = true;
@GuardedBy("this")
private boolean mBpfTimesAvailable = true;
// We use the freq count obtained from /proc/uid_time_in_state to decide how many longs // We use the freq count obtained from /proc/uid_time_in_state to decide how many longs
// to read from each /proc/uid/<uid>/time_in_state. On the first read, verify if this is // to read from each /proc/uid/<uid>/time_in_state. On the first read, verify if this is
// correct and if not, set {@link #mSingleUidCpuTimesAvailable} to false. This flag will // correct and if not, set {@link #mSingleUidCpuTimesAvailable} to false. This flag will
@@ -62,6 +64,8 @@ public class KernelSingleUidTimeReader {
private final Injector mInjector; private final Injector mInjector;
private static final native boolean canReadBpfTimes();
KernelSingleUidTimeReader(int cpuFreqsCount) { KernelSingleUidTimeReader(int cpuFreqsCount) {
this(cpuFreqsCount, new Injector()); this(cpuFreqsCount, new Injector());
} }
@@ -83,6 +87,18 @@ public class KernelSingleUidTimeReader {
if (!mSingleUidCpuTimesAvailable) { if (!mSingleUidCpuTimesAvailable) {
return null; return null;
} }
if (mBpfTimesAvailable) {
final long[] cpuTimesMs = mInjector.readBpfData(uid);
if (cpuTimesMs.length == 0) {
mBpfTimesAvailable = false;
} else if (!mCpuFreqsCountVerified && cpuTimesMs.length != mCpuFreqsCount) {
mSingleUidCpuTimesAvailable = false;
return null;
} else {
mCpuFreqsCountVerified = true;
return computeDelta(uid, cpuTimesMs);
}
}
// Read total cpu times from the proc file. // Read total cpu times from the proc file.
final String procFile = new StringBuilder(PROC_FILE_DIR) final String procFile = new StringBuilder(PROC_FILE_DIR)
.append(uid) .append(uid)
@@ -230,6 +246,8 @@ public class KernelSingleUidTimeReader {
public byte[] readData(String procFile) throws IOException { public byte[] readData(String procFile) throws IOException {
return Files.readAllBytes(Paths.get(procFile)); return Files.readAllBytes(Paths.get(procFile));
} }
public native long[] readBpfData(int uid);
} }
@VisibleForTesting @VisibleForTesting

View File

@@ -208,6 +208,7 @@ cc_library_shared {
"com_android_internal_os_ClassLoaderFactory.cpp", "com_android_internal_os_ClassLoaderFactory.cpp",
"com_android_internal_os_FuseAppLoop.cpp", "com_android_internal_os_FuseAppLoop.cpp",
"com_android_internal_os_KernelCpuUidBpfMapReader.cpp", "com_android_internal_os_KernelCpuUidBpfMapReader.cpp",
"com_android_internal_os_KernelSingleUidTimeReader.cpp",
"com_android_internal_os_Zygote.cpp", "com_android_internal_os_Zygote.cpp",
"com_android_internal_os_ZygoteInit.cpp", "com_android_internal_os_ZygoteInit.cpp",
"com_android_internal_util_VirtualRefBasePtr.cpp", "com_android_internal_util_VirtualRefBasePtr.cpp",

View File

@@ -231,6 +231,7 @@ extern int register_com_android_internal_os_AtomicDirectory(JNIEnv *env);
extern int register_com_android_internal_os_ClassLoaderFactory(JNIEnv* env); extern int register_com_android_internal_os_ClassLoaderFactory(JNIEnv* env);
extern int register_com_android_internal_os_FuseAppLoop(JNIEnv* env); extern int register_com_android_internal_os_FuseAppLoop(JNIEnv* env);
extern int register_com_android_internal_os_KernelCpuUidBpfMapReader(JNIEnv *env); extern int register_com_android_internal_os_KernelCpuUidBpfMapReader(JNIEnv *env);
extern int register_com_android_internal_os_KernelSingleUidTimeReader(JNIEnv *env);
extern int register_com_android_internal_os_Zygote(JNIEnv *env); extern int register_com_android_internal_os_Zygote(JNIEnv *env);
extern int register_com_android_internal_os_ZygoteInit(JNIEnv *env); extern int register_com_android_internal_os_ZygoteInit(JNIEnv *env);
extern int register_com_android_internal_util_VirtualRefBasePtr(JNIEnv *env); extern int register_com_android_internal_util_VirtualRefBasePtr(JNIEnv *env);
@@ -1642,6 +1643,7 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_com_android_internal_os_AtomicDirectory), REG_JNI(register_com_android_internal_os_AtomicDirectory),
REG_JNI(register_com_android_internal_os_FuseAppLoop), REG_JNI(register_com_android_internal_os_FuseAppLoop),
REG_JNI(register_com_android_internal_os_KernelCpuUidBpfMapReader), REG_JNI(register_com_android_internal_os_KernelCpuUidBpfMapReader),
REG_JNI(register_com_android_internal_os_KernelSingleUidTimeReader),
}; };
/* /*

View File

@@ -0,0 +1,54 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "core_jni_helpers.h"
#include <cputimeinstate.h>
namespace android {
static constexpr uint64_t NSEC_PER_MSEC = 1000000;
static jlongArray copyVecsToArray(JNIEnv *env, std::vector<std::vector<uint64_t>> &vec) {
jsize s = 0;
for (const auto &subVec : vec) s += subVec.size();
jlongArray ar = env->NewLongArray(s);
jsize start = 0;
for (auto &subVec : vec) {
for (uint32_t i = 0; i < subVec.size(); ++i) subVec[i] /= NSEC_PER_MSEC;
env->SetLongArrayRegion(ar, start, subVec.size(),
reinterpret_cast<const jlong*>(subVec.data()));
start += subVec.size();
}
return ar;
}
static jlongArray getUidCpuFreqTimeMs(JNIEnv *env, jclass, jint uid) {
auto out = android::bpf::getUidCpuFreqTimes(uid);
if (!out) return env->NewLongArray(0);
return copyVecsToArray(env, out.value());
}
static const JNINativeMethod g_single_methods[] = {
{"readBpfData", "(I)[J", (void *)getUidCpuFreqTimeMs},
};
int register_com_android_internal_os_KernelSingleUidTimeReader(JNIEnv *env) {
return RegisterMethodsOrDie(env, "com/android/internal/os/KernelSingleUidTimeReader$Injector",
g_single_methods, NELEM(g_single_methods));
}
}

View File

@@ -31,20 +31,33 @@ import com.android.internal.os.KernelSingleUidTimeReader.Injector;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
@SmallTest @SmallTest
@RunWith(AndroidJUnit4.class) @RunWith(Parameterized.class)
public class KernelSingleUidTimeReaderTest { public class KernelSingleUidTimeReaderTest {
private final static int TEST_UID = 2222; private final static int TEST_UID = 2222;
private final static int TEST_FREQ_COUNT = 5; private final static int TEST_FREQ_COUNT = 5;
private KernelSingleUidTimeReader mReader; private KernelSingleUidTimeReader mReader;
private TestInjector mInjector; private TestInjector mInjector;
protected boolean mUseBpf;
@Parameters(name="useBpf={0}")
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][] { {true}, {false} });
}
public KernelSingleUidTimeReaderTest(boolean useBpf) {
mUseBpf = useBpf;
}
@Before @Before
public void setUp() { public void setUp() {
@@ -273,6 +286,7 @@ public class KernelSingleUidTimeReaderTest {
class TestInjector extends Injector { class TestInjector extends Injector {
private byte[] mData; private byte[] mData;
private long[] mBpfData;
private boolean mThrowExcpetion; private boolean mThrowExcpetion;
@Override @Override
@@ -284,6 +298,14 @@ public class KernelSingleUidTimeReaderTest {
} }
} }
@Override
public long[] readBpfData(int uid) {
if (!mUseBpf || mBpfData == null) {
return new long[0];
}
return mBpfData;
}
public void setData(long[] cpuTimes) { public void setData(long[] cpuTimes) {
final ByteBuffer buffer = ByteBuffer.allocate(cpuTimes.length * Long.BYTES); final ByteBuffer buffer = ByteBuffer.allocate(cpuTimes.length * Long.BYTES);
buffer.order(ByteOrder.nativeOrder()); buffer.order(ByteOrder.nativeOrder());
@@ -291,6 +313,7 @@ public class KernelSingleUidTimeReaderTest {
buffer.putLong(time / 10); buffer.putLong(time / 10);
} }
mData = buffer.array(); mData = buffer.array();
mBpfData = cpuTimes.clone();
} }
public void letReadDataThrowException(boolean throwException) { public void letReadDataThrowException(boolean throwException) {