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.