Loading apct-tests/perftests/core/src/android/os/TracePerfTest.java 0 → 100644 +86 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2018 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. */ package android.os; import android.perftests.utils.BenchmarkState; import android.perftests.utils.PerfStatusReporter; import android.perftests.utils.ShellHelper; import android.support.test.runner.AndroidJUnit4; import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) public class TracePerfTest { @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); @BeforeClass public static void startTracing() { ShellHelper.runShellCommandRaw("atrace -c --async_start -a *"); } @AfterClass public static void endTracing() { ShellHelper.runShellCommandRaw("atrace --async_stop"); } @Before public void verifyTracingEnabled() { Assert.assertTrue(Trace.isEnabled()); } @Test public void testEnabled() { BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); while (state.keepRunning()) { Trace.isEnabled(); } } @Test public void testBeginEndSection() { BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); while (state.keepRunning()) { Trace.beginSection("testBeginEndSection"); Trace.endSection(); } } @Test public void testAsyncBeginEnd() { BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); while (state.keepRunning()) { Trace.beginAsyncSection("testAsyncBeginEnd", 42); Trace.endAsyncSection("testAsyncBeginEnd", 42); } } @Test public void testCounter() { BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); while (state.keepRunning()) { Trace.setCounter("testCounter", 123); } } } apct-tests/perftests/utils/src/android/perftests/utils/ShellHelper.java +8 −0 Original line number Original line Diff line number Diff line Loading @@ -37,6 +37,14 @@ public final class ShellHelper { @NonNull @NonNull public static String runShellCommand(@NonNull String template, Object...args) { public static String runShellCommand(@NonNull String template, Object...args) { String command = String.format(template, args); String command = String.format(template, args); return runShellCommandRaw(command); } /** * Runs a Shell command, returning a trimmed response. */ @NonNull public static String runShellCommandRaw(@NonNull String command) { UiAutomation automan = InstrumentationRegistry.getInstrumentation() UiAutomation automan = InstrumentationRegistry.getInstrumentation() .getUiAutomation(); .getUiAutomation(); ParcelFileDescriptor pfd = automan.executeShellCommand(command); ParcelFileDescriptor pfd = automan.executeShellCommand(command); Loading api/current.txt +4 −0 Original line number Original line Diff line number Diff line Loading @@ -33286,8 +33286,12 @@ package android.os { } } public final class Trace { public final class Trace { method public static void beginAsyncSection(java.lang.String, int); method public static void beginSection(java.lang.String); method public static void beginSection(java.lang.String); method public static void endAsyncSection(java.lang.String, int); method public static void endSection(); method public static void endSection(); method public static boolean isEnabled(); method public static void setCounter(java.lang.String, int); } } public class TransactionTooLargeException extends android.os.RemoteException { public class TransactionTooLargeException extends android.os.RemoteException { core/java/android/os/Trace.java +51 −0 Original line number Original line Diff line number Diff line Loading @@ -287,6 +287,19 @@ public final class Trace { } } } } /** * Checks whether or not tracing is currently enabled. This is useful to avoid intermediate * string creation for trace sections that require formatting. It is not necessary * to guard all Trace method calls as they internally already check this. However it is * recommended to use this to prevent creating any temporary objects that would then be * passed to those methods to reduce runtime cost when tracing isn't enabled. * * @return true if tracing is currently enabled, false otherwise */ public static boolean isEnabled() { return isTagEnabled(TRACE_TAG_APP); } /** /** * Writes a trace message to indicate that a given section of code has begun. This call must * Writes a trace message to indicate that a given section of code has begun. This call must * be followed by a corresponding call to {@link #endSection()} on the same thread. * be followed by a corresponding call to {@link #endSection()} on the same thread. Loading Loading @@ -319,4 +332,42 @@ public final class Trace { nativeTraceEnd(TRACE_TAG_APP); nativeTraceEnd(TRACE_TAG_APP); } } } } /** * Writes a trace message to indicate that a given section of code has * begun. Must be followed by a call to {@link #endAsyncSection(String, int)} with the same * methodName and cookie. Unlike {@link #beginSection(String)} and {@link #endSection()}, * asynchronous events do not need to be nested. The name and cookie used to * begin an event must be used to end it. * * @param methodName The method name to appear in the trace. * @param cookie Unique identifier for distinguishing simultaneous events */ public static void beginAsyncSection(String methodName, int cookie) { asyncTraceBegin(TRACE_TAG_APP, methodName, cookie); } /** * Writes a trace message to indicate that the current method has ended. * Must be called exactly once for each call to {@link #beginAsyncSection(String, int)} * using the same name and cookie. * * @param methodName The method name to appear in the trace. * @param cookie Unique identifier for distinguishing simultaneous events */ public static void endAsyncSection(String methodName, int cookie) { asyncTraceEnd(TRACE_TAG_APP, methodName, cookie); } /** * Writes trace message to indicate the value of a given counter. * * @param counterName The counter name to appear in the trace. * @param counterValue The counter value. */ public static void setCounter(String counterName, int counterValue) { if (isTagEnabled(TRACE_TAG_APP)) { nativeTraceCounter(TRACE_TAG_APP, counterName, counterValue); } } } } core/jni/android_os_Trace.cpp +38 −51 Original line number Original line Diff line number Diff line Loading @@ -14,93 +14,80 @@ * limitations under the License. * limitations under the License. */ */ #define LOG_TAG "Trace" #include <jni.h> // #define LOG_NDEBUG 0 #include <inttypes.h> #include <cutils/trace.h> #include <cutils/trace.h> #include <utils/String8.h> #include <log/log.h> #include <log/log.h> #include <nativehelper/JNIHelp.h> #include <nativehelper/JNIHelp.h> #include <nativehelper/ScopedUtfChars.h> #include <nativehelper/ScopedStringChars.h> #include <array> namespace android { namespace android { static void sanitizeString(String8& utf8Chars) { inline static void sanitizeString(char* str, size_t size) { size_t size = utf8Chars.size(); char* str = utf8Chars.lockBuffer(size); for (size_t i = 0; i < size; i++) { for (size_t i = 0; i < size; i++) { char c = str[i]; char c = str[i]; if (c == '\0' || c == '\n' || c == '|') { if (c == '\0' || c == '\n' || c == '|') { str[i] = ' '; str[i] = ' '; } } } } utf8Chars.unlockBuffer(); } } static jlong android_os_Trace_nativeGetEnabledTags(JNIEnv* env, jclass clazz) { inline static void getString(JNIEnv* env, jstring jstring, char* outBuffer, jsize maxSize) { jsize size = std::min(env->GetStringLength(jstring), maxSize); env->GetStringUTFRegion(jstring, 0, size, outBuffer); sanitizeString(outBuffer, size); outBuffer[size] = '\0'; } template<typename F> inline static void withString(JNIEnv* env, jstring jstr, F callback) { std::array<char, 1024> buffer; getString(env, jstr, buffer.data(), buffer.size()); callback(buffer.data()); } static jlong android_os_Trace_nativeGetEnabledTags(JNIEnv*, jclass) { return atrace_get_enabled_tags(); return atrace_get_enabled_tags(); } } static void android_os_Trace_nativeTraceCounter(JNIEnv* env, jclass clazz, static void android_os_Trace_nativeTraceCounter(JNIEnv* env, jclass, jlong tag, jstring nameStr, jint value) { jlong tag, jstring nameStr, jint value) { ScopedUtfChars name(env, nameStr); withString(env, nameStr, [tag, value](char* str) { atrace_int(tag, str, value); ALOGV("%s: %" PRId64 " %s %d", __FUNCTION__, tag, name.c_str(), value); }); atrace_int(tag, name.c_str(), value); } } static void android_os_Trace_nativeTraceBegin(JNIEnv* env, jclass clazz, static void android_os_Trace_nativeTraceBegin(JNIEnv* env, jclass, jlong tag, jstring nameStr) { jlong tag, jstring nameStr) { ScopedStringChars jchars(env, nameStr); withString(env, nameStr, [tag](char* str) { String8 utf8Chars(reinterpret_cast<const char16_t*>(jchars.get()), jchars.size()); atrace_begin(tag, str); sanitizeString(utf8Chars); }); ALOGV("%s: %" PRId64 " %s", __FUNCTION__, tag, utf8Chars.string()); atrace_begin(tag, utf8Chars.string()); } } static void android_os_Trace_nativeTraceEnd(JNIEnv* env, jclass clazz, static void android_os_Trace_nativeTraceEnd(JNIEnv*, jclass, jlong tag) { jlong tag) { ALOGV("%s: %" PRId64, __FUNCTION__, tag); atrace_end(tag); atrace_end(tag); } } static void android_os_Trace_nativeAsyncTraceBegin(JNIEnv* env, jclass clazz, static void android_os_Trace_nativeAsyncTraceBegin(JNIEnv* env, jclass, jlong tag, jstring nameStr, jint cookie) { jlong tag, jstring nameStr, jint cookie) { ScopedStringChars jchars(env, nameStr); withString(env, nameStr, [tag, cookie](char* str) { String8 utf8Chars(reinterpret_cast<const char16_t*>(jchars.get()), jchars.size()); atrace_async_begin(tag, str, cookie); sanitizeString(utf8Chars); }); ALOGV("%s: %" PRId64 " %s %d", __FUNCTION__, tag, utf8Chars.string(), cookie); atrace_async_begin(tag, utf8Chars.string(), cookie); } } static void android_os_Trace_nativeAsyncTraceEnd(JNIEnv* env, jclass clazz, static void android_os_Trace_nativeAsyncTraceEnd(JNIEnv* env, jclass, jlong tag, jstring nameStr, jint cookie) { jlong tag, jstring nameStr, jint cookie) { ScopedStringChars jchars(env, nameStr); withString(env, nameStr, [tag, cookie](char* str) { String8 utf8Chars(reinterpret_cast<const char16_t*>(jchars.get()), jchars.size()); atrace_async_end(tag, str, cookie); sanitizeString(utf8Chars); }); ALOGV("%s: %" PRId64 " %s %d", __FUNCTION__, tag, utf8Chars.string(), cookie); atrace_async_end(tag, utf8Chars.string(), cookie); } } static void android_os_Trace_nativeSetAppTracingAllowed(JNIEnv* env, static void android_os_Trace_nativeSetAppTracingAllowed(JNIEnv*, jclass, jboolean allowed) { jclass clazz, jboolean allowed) { ALOGV("%s: %d", __FUNCTION__, allowed); atrace_set_debuggable(allowed); atrace_set_debuggable(allowed); } } static void android_os_Trace_nativeSetTracingEnabled(JNIEnv* env, static void android_os_Trace_nativeSetTracingEnabled(JNIEnv*, jclass, jboolean enabled) { jclass clazz, jboolean enabled) { ALOGV("%s: %d", __FUNCTION__, enabled); atrace_set_tracing_enabled(enabled); atrace_set_tracing_enabled(enabled); } } Loading Loading
apct-tests/perftests/core/src/android/os/TracePerfTest.java 0 → 100644 +86 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2018 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. */ package android.os; import android.perftests.utils.BenchmarkState; import android.perftests.utils.PerfStatusReporter; import android.perftests.utils.ShellHelper; import android.support.test.runner.AndroidJUnit4; import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) public class TracePerfTest { @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); @BeforeClass public static void startTracing() { ShellHelper.runShellCommandRaw("atrace -c --async_start -a *"); } @AfterClass public static void endTracing() { ShellHelper.runShellCommandRaw("atrace --async_stop"); } @Before public void verifyTracingEnabled() { Assert.assertTrue(Trace.isEnabled()); } @Test public void testEnabled() { BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); while (state.keepRunning()) { Trace.isEnabled(); } } @Test public void testBeginEndSection() { BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); while (state.keepRunning()) { Trace.beginSection("testBeginEndSection"); Trace.endSection(); } } @Test public void testAsyncBeginEnd() { BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); while (state.keepRunning()) { Trace.beginAsyncSection("testAsyncBeginEnd", 42); Trace.endAsyncSection("testAsyncBeginEnd", 42); } } @Test public void testCounter() { BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); while (state.keepRunning()) { Trace.setCounter("testCounter", 123); } } }
apct-tests/perftests/utils/src/android/perftests/utils/ShellHelper.java +8 −0 Original line number Original line Diff line number Diff line Loading @@ -37,6 +37,14 @@ public final class ShellHelper { @NonNull @NonNull public static String runShellCommand(@NonNull String template, Object...args) { public static String runShellCommand(@NonNull String template, Object...args) { String command = String.format(template, args); String command = String.format(template, args); return runShellCommandRaw(command); } /** * Runs a Shell command, returning a trimmed response. */ @NonNull public static String runShellCommandRaw(@NonNull String command) { UiAutomation automan = InstrumentationRegistry.getInstrumentation() UiAutomation automan = InstrumentationRegistry.getInstrumentation() .getUiAutomation(); .getUiAutomation(); ParcelFileDescriptor pfd = automan.executeShellCommand(command); ParcelFileDescriptor pfd = automan.executeShellCommand(command); Loading
api/current.txt +4 −0 Original line number Original line Diff line number Diff line Loading @@ -33286,8 +33286,12 @@ package android.os { } } public final class Trace { public final class Trace { method public static void beginAsyncSection(java.lang.String, int); method public static void beginSection(java.lang.String); method public static void beginSection(java.lang.String); method public static void endAsyncSection(java.lang.String, int); method public static void endSection(); method public static void endSection(); method public static boolean isEnabled(); method public static void setCounter(java.lang.String, int); } } public class TransactionTooLargeException extends android.os.RemoteException { public class TransactionTooLargeException extends android.os.RemoteException {
core/java/android/os/Trace.java +51 −0 Original line number Original line Diff line number Diff line Loading @@ -287,6 +287,19 @@ public final class Trace { } } } } /** * Checks whether or not tracing is currently enabled. This is useful to avoid intermediate * string creation for trace sections that require formatting. It is not necessary * to guard all Trace method calls as they internally already check this. However it is * recommended to use this to prevent creating any temporary objects that would then be * passed to those methods to reduce runtime cost when tracing isn't enabled. * * @return true if tracing is currently enabled, false otherwise */ public static boolean isEnabled() { return isTagEnabled(TRACE_TAG_APP); } /** /** * Writes a trace message to indicate that a given section of code has begun. This call must * Writes a trace message to indicate that a given section of code has begun. This call must * be followed by a corresponding call to {@link #endSection()} on the same thread. * be followed by a corresponding call to {@link #endSection()} on the same thread. Loading Loading @@ -319,4 +332,42 @@ public final class Trace { nativeTraceEnd(TRACE_TAG_APP); nativeTraceEnd(TRACE_TAG_APP); } } } } /** * Writes a trace message to indicate that a given section of code has * begun. Must be followed by a call to {@link #endAsyncSection(String, int)} with the same * methodName and cookie. Unlike {@link #beginSection(String)} and {@link #endSection()}, * asynchronous events do not need to be nested. The name and cookie used to * begin an event must be used to end it. * * @param methodName The method name to appear in the trace. * @param cookie Unique identifier for distinguishing simultaneous events */ public static void beginAsyncSection(String methodName, int cookie) { asyncTraceBegin(TRACE_TAG_APP, methodName, cookie); } /** * Writes a trace message to indicate that the current method has ended. * Must be called exactly once for each call to {@link #beginAsyncSection(String, int)} * using the same name and cookie. * * @param methodName The method name to appear in the trace. * @param cookie Unique identifier for distinguishing simultaneous events */ public static void endAsyncSection(String methodName, int cookie) { asyncTraceEnd(TRACE_TAG_APP, methodName, cookie); } /** * Writes trace message to indicate the value of a given counter. * * @param counterName The counter name to appear in the trace. * @param counterValue The counter value. */ public static void setCounter(String counterName, int counterValue) { if (isTagEnabled(TRACE_TAG_APP)) { nativeTraceCounter(TRACE_TAG_APP, counterName, counterValue); } } } }
core/jni/android_os_Trace.cpp +38 −51 Original line number Original line Diff line number Diff line Loading @@ -14,93 +14,80 @@ * limitations under the License. * limitations under the License. */ */ #define LOG_TAG "Trace" #include <jni.h> // #define LOG_NDEBUG 0 #include <inttypes.h> #include <cutils/trace.h> #include <cutils/trace.h> #include <utils/String8.h> #include <log/log.h> #include <log/log.h> #include <nativehelper/JNIHelp.h> #include <nativehelper/JNIHelp.h> #include <nativehelper/ScopedUtfChars.h> #include <nativehelper/ScopedStringChars.h> #include <array> namespace android { namespace android { static void sanitizeString(String8& utf8Chars) { inline static void sanitizeString(char* str, size_t size) { size_t size = utf8Chars.size(); char* str = utf8Chars.lockBuffer(size); for (size_t i = 0; i < size; i++) { for (size_t i = 0; i < size; i++) { char c = str[i]; char c = str[i]; if (c == '\0' || c == '\n' || c == '|') { if (c == '\0' || c == '\n' || c == '|') { str[i] = ' '; str[i] = ' '; } } } } utf8Chars.unlockBuffer(); } } static jlong android_os_Trace_nativeGetEnabledTags(JNIEnv* env, jclass clazz) { inline static void getString(JNIEnv* env, jstring jstring, char* outBuffer, jsize maxSize) { jsize size = std::min(env->GetStringLength(jstring), maxSize); env->GetStringUTFRegion(jstring, 0, size, outBuffer); sanitizeString(outBuffer, size); outBuffer[size] = '\0'; } template<typename F> inline static void withString(JNIEnv* env, jstring jstr, F callback) { std::array<char, 1024> buffer; getString(env, jstr, buffer.data(), buffer.size()); callback(buffer.data()); } static jlong android_os_Trace_nativeGetEnabledTags(JNIEnv*, jclass) { return atrace_get_enabled_tags(); return atrace_get_enabled_tags(); } } static void android_os_Trace_nativeTraceCounter(JNIEnv* env, jclass clazz, static void android_os_Trace_nativeTraceCounter(JNIEnv* env, jclass, jlong tag, jstring nameStr, jint value) { jlong tag, jstring nameStr, jint value) { ScopedUtfChars name(env, nameStr); withString(env, nameStr, [tag, value](char* str) { atrace_int(tag, str, value); ALOGV("%s: %" PRId64 " %s %d", __FUNCTION__, tag, name.c_str(), value); }); atrace_int(tag, name.c_str(), value); } } static void android_os_Trace_nativeTraceBegin(JNIEnv* env, jclass clazz, static void android_os_Trace_nativeTraceBegin(JNIEnv* env, jclass, jlong tag, jstring nameStr) { jlong tag, jstring nameStr) { ScopedStringChars jchars(env, nameStr); withString(env, nameStr, [tag](char* str) { String8 utf8Chars(reinterpret_cast<const char16_t*>(jchars.get()), jchars.size()); atrace_begin(tag, str); sanitizeString(utf8Chars); }); ALOGV("%s: %" PRId64 " %s", __FUNCTION__, tag, utf8Chars.string()); atrace_begin(tag, utf8Chars.string()); } } static void android_os_Trace_nativeTraceEnd(JNIEnv* env, jclass clazz, static void android_os_Trace_nativeTraceEnd(JNIEnv*, jclass, jlong tag) { jlong tag) { ALOGV("%s: %" PRId64, __FUNCTION__, tag); atrace_end(tag); atrace_end(tag); } } static void android_os_Trace_nativeAsyncTraceBegin(JNIEnv* env, jclass clazz, static void android_os_Trace_nativeAsyncTraceBegin(JNIEnv* env, jclass, jlong tag, jstring nameStr, jint cookie) { jlong tag, jstring nameStr, jint cookie) { ScopedStringChars jchars(env, nameStr); withString(env, nameStr, [tag, cookie](char* str) { String8 utf8Chars(reinterpret_cast<const char16_t*>(jchars.get()), jchars.size()); atrace_async_begin(tag, str, cookie); sanitizeString(utf8Chars); }); ALOGV("%s: %" PRId64 " %s %d", __FUNCTION__, tag, utf8Chars.string(), cookie); atrace_async_begin(tag, utf8Chars.string(), cookie); } } static void android_os_Trace_nativeAsyncTraceEnd(JNIEnv* env, jclass clazz, static void android_os_Trace_nativeAsyncTraceEnd(JNIEnv* env, jclass, jlong tag, jstring nameStr, jint cookie) { jlong tag, jstring nameStr, jint cookie) { ScopedStringChars jchars(env, nameStr); withString(env, nameStr, [tag, cookie](char* str) { String8 utf8Chars(reinterpret_cast<const char16_t*>(jchars.get()), jchars.size()); atrace_async_end(tag, str, cookie); sanitizeString(utf8Chars); }); ALOGV("%s: %" PRId64 " %s %d", __FUNCTION__, tag, utf8Chars.string(), cookie); atrace_async_end(tag, utf8Chars.string(), cookie); } } static void android_os_Trace_nativeSetAppTracingAllowed(JNIEnv* env, static void android_os_Trace_nativeSetAppTracingAllowed(JNIEnv*, jclass, jboolean allowed) { jclass clazz, jboolean allowed) { ALOGV("%s: %d", __FUNCTION__, allowed); atrace_set_debuggable(allowed); atrace_set_debuggable(allowed); } } static void android_os_Trace_nativeSetTracingEnabled(JNIEnv* env, static void android_os_Trace_nativeSetTracingEnabled(JNIEnv*, jclass, jboolean enabled) { jclass clazz, jboolean enabled) { ALOGV("%s: %d", __FUNCTION__, enabled); atrace_set_tracing_enabled(enabled); atrace_set_tracing_enabled(enabled); } } Loading