Merge "Block trace until redaction is finalized" into main
diff --git a/apex/Android.bp b/apex/Android.bp
index e2cba39..eee9315 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -27,30 +27,86 @@
certificate: "com.android.profiling",
}
-apex {
+soong_config_module_type {
+ name: "custom_apex",
+ module_type: "apex",
+ config_namespace: "ANDROID",
+ bool_variables: [
+ "release_package_profiling_module",
+ ],
+ properties: [
+ "enabled",
+ ],
+}
+
+custom_apex {
+ // This apex will be enabled with release_package_profiling_module flag
+ enabled: false,
+ soong_config_variables: {
+ release_package_profiling_module: {
+ enabled: true,
+ },
+ },
+
name: "com.android.profiling",
manifest: "manifest.json",
file_contexts: ":apex.test-file_contexts",
key: "com.android.profiling.key",
certificate: ":com.android.profiling.certificate",
- defaults: ["com.android.profiling-defaults"],
+ defaults: ["v-launched-apex-module"],
min_sdk_version: "34",
-}
-apex_defaults {
- name: "com.android.profiling-defaults",
bootclasspath_fragments: ["com.android.profiling-bootclasspath-fragment"],
systemserverclasspath_fragments: ["com.android.profiling-systemserverclasspath-fragment"],
- defaults: ["v-launched-apex-module"],
}
-systemserverclasspath_fragment {
+soong_config_module_type {
+ name: "custom_systemserverclasspath_fragment",
+ module_type: "systemserverclasspath_fragment",
+ config_namespace: "ANDROID",
+ bool_variables: [
+ "release_package_profiling_module",
+ ],
+ properties: [
+ "enabled",
+ ],
+}
+
+custom_systemserverclasspath_fragment {
+ // This fragment will be enabled with release_package_profiling_module flag
+ enabled: false,
+ soong_config_variables: {
+ release_package_profiling_module: {
+ enabled: true,
+ },
+ },
+
name: "com.android.profiling-systemserverclasspath-fragment",
standalone_contents: ["service-profiling"],
apex_available: ["com.android.profiling"],
}
-bootclasspath_fragment {
+soong_config_module_type {
+ name: "custom_bootclasspath_fragment",
+ module_type: "bootclasspath_fragment",
+ config_namespace: "ANDROID",
+ bool_variables: [
+ "release_package_profiling_module",
+ ],
+ properties: [
+ "enabled",
+ ],
+}
+
+custom_bootclasspath_fragment {
+ // This fragment will be enabled with release_package_profiling_module flag
+ enabled: false,
+ soong_config_variables: {
+ release_package_profiling_module: {
+ enabled: true,
+ },
+ },
+
name: "com.android.profiling-bootclasspath-fragment",
contents: ["framework-profiling"],
apex_available: ["com.android.profiling"],
diff --git a/framework/api/current.txt b/framework/api/current.txt
index a98f106..705a99f 100644
--- a/framework/api/current.txt
+++ b/framework/api/current.txt
@@ -2,9 +2,9 @@
package android.os {
@FlaggedApi("android.os.profiling.telemetry_apis") public final class ProfilingManager {
- method public void registerForProfilingResults(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.os.ProfilingResult>);
+ method public void registerForAllProfilingResults(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.os.ProfilingResult>);
method public void requestProfiling(@NonNull byte[], @Nullable String, @Nullable android.os.CancellationSignal, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<android.os.ProfilingResult>);
- method public void unregisterForProfilingResults(@NonNull java.util.function.Consumer<android.os.ProfilingResult>);
+ method public void unregisterForAllProfilingResults(@Nullable java.util.function.Consumer<android.os.ProfilingResult>);
}
@FlaggedApi("android.os.profiling.telemetry_apis") public final class ProfilingResult implements android.os.Parcelable {
diff --git a/framework/java/android/os/ProfilingManager.java b/framework/java/android/os/ProfilingManager.java
index fc8e4d1..29b448d 100644
--- a/framework/java/android/os/ProfilingManager.java
+++ b/framework/java/android/os/ProfilingManager.java
@@ -71,7 +71,7 @@
}
/**
- * Request profiling via perfetto.
+ * Request system profiling.
*
* <p class="note"> Note: use of this API directly is not recommended for most use cases.
* Please use the higher level wrappers provided by androidx that will construct the request
@@ -79,17 +79,28 @@
*
* <p class="note"> Note: requests are not guaranteed to be filled.</p>
*
- * <p class="note"> Note: a listener must be set for the request to be considered for
- * fulfillment. Listeners can be set in this method, with {@see #registerForProfilingResult},
- * or both. If no listener is set the request will be discarded.</p>
+ * <p class="note"> Note: Both a listener and executor must be set for the request to be
+ * considered for fulfillment.
+ * Listeners can be set in this method, with {@link #registerForAllProfilingResults}, or both.
+ * If no listener and executor is set the request will be discarded.</p>
*
* @param profilingRequest byte array representation of ProfilingRequest proto containing all
- * necessary information about the collection being requested.
+ * necessary information about the collection being requested.
+ * Use of androidx wrappers is recommended over generating this directly.
* @param tag Caller defined data to help identify the output.
* @param cancellationSignal for caller requested cancellation.
- * Results will be returned if available.
- * @param executor The executor to call back with.
- * @param listener Listener to be triggered with result.
+ * Results will be returned if available.
+ * If this is null, the requesting app will not be able to stop the collection.
+ * The collection will stop after timing out with either the provided
+ * configurations or with system defaults
+ * @param executor The executor to call back with.
+ * Will only be used for the listener provided in this method.
+ * If this is null, and no global executor and listener combinations are
+ * registered at the time of the request, the request will be dropped.
+ * @param listener Listener to be triggered with result. Any global listeners registered via
+ * {@link #registerForAllProfilingResults} will also be triggered. If this is
+ * null, and no global listener and executor combinations are registered at
+ * the time of the request, the request will be dropped.
*/
public void requestProfiling(
@NonNull byte[] profilingRequest,
@@ -148,12 +159,13 @@
}
/**
- * Register a listener to be called for all profiling results.
+ * Register a listener to be called for all profiling results for this uid. Listeners set here
+ * will be called in addition to any provided with the request.
*
* @param executor The executor to call back with.
* @param listener Listener to be triggered with result.
*/
- public void registerForProfilingResults(
+ public void registerForAllProfilingResults(
@NonNull Executor executor,
@NonNull Consumer<ProfilingResult> listener) {
synchronized (sLock) {
@@ -162,24 +174,41 @@
}
/**
- * Unregister a listener to be called for all profiling results. If no listener is provided,
- * all listeners for this process that were not submitted with a currently running trace will
- * be removed.
+ * Unregister a listener that was to be called for all profiling results. If no listener is
+ * provided, all listeners for this process that were not submitted with a profiling request
+ * will be removed.
*
- * @param listener Listener to unregister and no longer be triggered with the result.
+ * @param listener Listener to unregister and no longer be triggered with the results.
+ * Null to remove all global listeners for this uid.
*/
- public void unregisterForProfilingResults(
- @NonNull Consumer<ProfilingResult> listener) {
+ public void unregisterForAllProfilingResults(
+ @Nullable Consumer<ProfilingResult> listener) {
synchronized (sLock) {
if (mCallbacks.isEmpty()) {
// No callbacks, nothing to remove.
return;
}
- for (int i = 0; i < mCallbacks.size(); i++) {
- ProfilingRequestCallbackWrapper wrapper = mCallbacks.get(i);
- if (listener.equals(wrapper.mListener)) {
- mCallbacks.remove(i);
- return;
+
+ if (listener == null) {
+ // Remove all global listeners.
+ ArrayList<ProfilingRequestCallbackWrapper> listenersToRemove = new ArrayList<>();
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ ProfilingRequestCallbackWrapper wrapper = mCallbacks.get(i);
+ // Only remove global listeners which are not tied to a specific request. These
+ // can be identified by checking that they do not have an associated key.
+ if (wrapper.mKey == null) {
+ listenersToRemove.add(wrapper);
+ }
+ }
+ mCallbacks.removeAll(listenersToRemove);
+ } else {
+ // Remove the provided listener only.
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ ProfilingRequestCallbackWrapper wrapper = mCallbacks.get(i);
+ if (listener.equals(wrapper.mListener)) {
+ mCallbacks.remove(i);
+ return;
+ }
}
}
}
@@ -202,7 +231,7 @@
mProfilingService.registerResultsCallback(new IProfilingResultCallback.Stub() {
/**
- * Called by {@see ProfilingService} when a result is ready,
+ * Called by {@link ProfilingService} when a result is ready,
* both for success and failure.
*/
@Override
@@ -257,7 +286,7 @@
}
/**
- * Called by {@see ProfilingService} when a trace is ready and need to be copied
+ * Called by {@link ProfilingService} when a trace is ready and need to be copied
* to callers internal storage.
*
* This method will open a new file and pass back the FileDescriptor for
@@ -309,8 +338,8 @@
final @NonNull Consumer<ProfilingResult> mListener;
/**
- * Unique key generated with each profiling request {@see #requestProfiling}, but not with
- * requests to register a listener only {@see #registerForProfilingResult}.
+ * Unique key generated with each profiling request {@link #requestProfiling}, but not with
+ * requests to register a listener only {@link #registerForAllProfilingResults}.
*
* Key is used to match the result with the listener added with the request so that it can
* removed after being triggered while the general registered callbacks remain active.