Merge "lpdump: Add info about super partition" into main
diff --git a/crypto-perf/Android.bp b/crypto-perf/Android.bp
deleted file mode 100644
index 8f575ca..0000000
--- a/crypto-perf/Android.bp
+++ /dev/null
@@ -1,35 +0,0 @@
-package {
-    default_applicable_licenses: ["system_extras_crypto-perf_license"],
-}
-
-// Added automatically by a large-scale-change
-// See: http://go/android-license-faq
-license {
-    name: "system_extras_crypto-perf_license",
-    visibility: [":__subpackages__"],
-    license_kinds: [
-        "SPDX-license-identifier-Apache-2.0",
-    ],
-    license_text: [
-        "NOTICE",
-    ],
-}
-
-cc_binary {
-    name: "crypto",
-
-    cflags: [
-        "-O0",
-        "-march=armv8-a+crypto",
-        "-Wall",
-        "-Werror",
-    ],
-    srcs: ["crypto.cpp"],
-
-    enabled: false,
-    arch: {
-        arm64: {
-            enabled: true,
-        },
-    },
-}
diff --git a/crypto-perf/NOTICE b/crypto-perf/NOTICE
deleted file mode 100644
index c77f135..0000000
--- a/crypto-perf/NOTICE
+++ /dev/null
@@ -1,190 +0,0 @@
-
-   Copyright (c) 2012, 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.
-
-   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.
-
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
diff --git a/crypto-perf/crypto.cpp b/crypto-perf/crypto.cpp
deleted file mode 100644
index a722832..0000000
--- a/crypto-perf/crypto.cpp
+++ /dev/null
@@ -1,165 +0,0 @@
-#include <ctype.h>
-#include <sched.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/resource.h>
-#include <sys/time.h>
-#include <unistd.h>
-#define USEC_PER_SEC 1000000ULL
-#define MAX_COUNT 1000000000ULL
-#define NUM_INSTS_GARBAGE 18
-
-// Contains information about benchmark options.
-typedef struct {
-    int cpu_to_lock;
-    int locked_freq;
-} command_data_t;
-
-void usage() {
-    printf("--------------------------------------------------------------------------------\n");
-    printf("Usage:");
-    printf("	crypto [--cpu_to_lock CPU] [--locked_freq FREQ_IN_KHZ]\n\n");
-    printf("!!!!!!Lock the desired core to a desired frequency before invoking this benchmark.\n");
-    printf("Hint: Set scaling_max_freq=scaling_min_freq=FREQ_IN_KHZ. FREQ_IN_KHZ "
-           "can be obtained from scaling_available_freq\n");
-    printf("--------------------------------------------------------------------------------\n");
-}
-
-int processOptions(int argc, char** argv, command_data_t* cmd_data) {
-    // Initialize the command_flags.
-    cmd_data->cpu_to_lock = 0;
-    cmd_data->locked_freq = 1;
-    for (int i = 1; i < argc; i++) {
-        if (argv[i][0] == '-') {
-            int* save_value = NULL;
-            if (strcmp(argv[i], "--cpu_to_lock") == 0) {
-                save_value = &cmd_data->cpu_to_lock;
-            } else if (strcmp(argv[i], "--locked_freq") == 0) {
-                save_value = &cmd_data->locked_freq;
-            } else {
-                printf("Unknown option %s\n", argv[i]);
-                return -1;
-            }
-            if (save_value) {
-                // Checking both characters without a strlen() call should be
-                // safe since as long as the argument exists, one character will
-                // be present (\0). And if the first character is '-', then
-                // there will always be a second character (\0 again).
-                if (i == argc - 1 || (argv[i + 1][0] == '-' && !isdigit(argv[i + 1][1]))) {
-                    printf("The option %s requires one argument.\n", argv[i]);
-                    return -1;
-                }
-                *save_value = (int)strtol(argv[++i], NULL, 0);
-            }
-        }
-    }
-    return 0;
-}
-/* Performs encryption on garbage values. In Cortex-A57 r0p1 and later
- * revisions, pairs of dependent AESE/AESMC and AESD/AESIMC instructions are
- * higher performance when adjacent, and in the described order below. */
-void garbage_encrypt() {
-    __asm__ __volatile__(
-            "aese  v0.16b, v4.16b ;"
-            "aesmc	v0.16b, v0.16b ;"
-            "aese  v1.16b, v4.16b ;"
-            "aesmc	v1.16b, v1.16b ;"
-            "aese  v2.16b, v4.16b ;"
-            "aesmc	v2.16b, v2.16b ;"
-            "aese  v0.16b, v5.16b ;"
-            "aesmc	v0.16b, v0.16b ;"
-            "aese  v1.16b, v5.16b ;"
-            "aesmc	v1.16b, v1.16b ;"
-            "aese  v2.16b, v5.16b ;"
-            "aesmc	v2.16b, v2.16b ;"
-            "aese  v0.16b, v6.16b ;"
-            "aesmc	v0.16b, v0.16b ;"
-            "aese  v1.16b, v6.16b ;"
-            "aesmc	v1.16b, v1.16b ;"
-            "aese  v2.16b, v6.16b ;"
-            "aesmc	v2.16b, v2.16b ;");
-}
-
-void garbage_decrypt() {
-    __asm__ __volatile__(
-            "aesd  v0.16b, v4.16b ;"
-            "aesimc	v0.16b, v0.16b ;"
-            "aesd  v1.16b, v4.16b ;"
-            "aesimc	v1.16b, v1.16b ;"
-            "aesd  v2.16b, v4.16b ;"
-            "aesimc	v2.16b, v2.16b ;"
-            "aesd  v0.16b, v5.16b ;"
-            "aesimc	v0.16b, v0.16b ;"
-            "aesd  v1.16b, v5.16b ;"
-            "aesimc	v1.16b, v1.16b ;"
-            "aesd  v2.16b, v5.16b ;"
-            "aesimc	v2.16b, v2.16b ;"
-            "aesd  v0.16b, v6.16b ;"
-            "aesimc	v0.16b, v0.16b ;"
-            "aesd  v1.16b, v6.16b ;"
-            "aesimc	v1.16b, v1.16b ;"
-            "aesd  v2.16b, v6.16b ;"
-            "aesimc	v2.16b, v2.16b ;");
-}
-
-int main(int argc, char** argv) {
-    usage();
-    command_data_t cmd_data;
-
-    if (processOptions(argc, argv, &cmd_data) == -1) {
-        usage();
-        return -1;
-    }
-    unsigned long long count = 0;
-    struct timeval begin_time, end_time, elapsed_time;
-    cpu_set_t cpuset;
-    CPU_ZERO(&cpuset);
-    CPU_SET(cmd_data.cpu_to_lock, &cpuset);
-    if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0) {
-        perror("sched_setaffinity failed");
-        return 1;
-    }
-    gettimeofday(&begin_time, NULL);
-    while (count < MAX_COUNT) {
-        garbage_encrypt();
-        count++;
-    }
-    gettimeofday(&end_time, NULL);
-    timersub(&end_time, &begin_time, &elapsed_time);
-    fprintf(stderr, "encrypt: %llu us\n",
-            elapsed_time.tv_sec * USEC_PER_SEC + elapsed_time.tv_usec);
-    fprintf(stderr, "encrypt instructions: %llu\n", MAX_COUNT * NUM_INSTS_GARBAGE);
-    fprintf(stderr, "encrypt instructions per second: %f\n",
-            (float)(MAX_COUNT * NUM_INSTS_GARBAGE * USEC_PER_SEC) /
-                    (elapsed_time.tv_sec * USEC_PER_SEC + elapsed_time.tv_usec));
-    if (cmd_data.locked_freq != 0) {
-        fprintf(stderr, "encrypt instructions per cycle: %f\n",
-                (float)(MAX_COUNT * NUM_INSTS_GARBAGE * USEC_PER_SEC) /
-                        ((elapsed_time.tv_sec * USEC_PER_SEC + elapsed_time.tv_usec) * 1000 *
-                         cmd_data.locked_freq));
-    }
-    printf("--------------------------------------------------------------------------------\n");
-
-    count = 0;
-    gettimeofday(&begin_time, NULL);
-    while (count < MAX_COUNT) {
-        garbage_decrypt();
-        count++;
-    }
-    gettimeofday(&end_time, NULL);
-    timersub(&end_time, &begin_time, &elapsed_time);
-    fprintf(stderr, "decrypt: %llu us\n",
-            elapsed_time.tv_sec * USEC_PER_SEC + elapsed_time.tv_usec);
-    fprintf(stderr, "decrypt instructions: %llu\n", MAX_COUNT * NUM_INSTS_GARBAGE);
-    fprintf(stderr, "decrypt instructions per second: %f\n",
-            (float)(MAX_COUNT * NUM_INSTS_GARBAGE * USEC_PER_SEC) /
-                    (elapsed_time.tv_sec * USEC_PER_SEC + elapsed_time.tv_usec));
-    if (cmd_data.locked_freq != 0) {
-        fprintf(stderr, "decrypt instructions per cycle: %f\n",
-                (float)(MAX_COUNT * NUM_INSTS_GARBAGE * USEC_PER_SEC) /
-                        ((elapsed_time.tv_sec * USEC_PER_SEC + elapsed_time.tv_usec) * 1000 *
-                         cmd_data.locked_freq));
-    }
-    return 0;
-}
diff --git a/profcollectd/libprofcollectd/config.rs b/profcollectd/libprofcollectd/config.rs
index 8724248..af71424 100644
--- a/profcollectd/libprofcollectd/config.rs
+++ b/profcollectd/libprofcollectd/config.rs
@@ -27,7 +27,7 @@
 use std::str::FromStr;
 use std::time::Duration;
 
-const PROFCOLLECT_CONFIG_NAMESPACE: &str = "profcollect_native_boot";
+const PROFCOLLECT_CONFIG_NAMESPACE: &str = "aconfig_flags.profcollect_native_boot";
 const PROFCOLLECT_NODE_ID_PROPERTY: &str = "persist.profcollectd.node_id";
 
 const DEFAULT_BINARY_FILTER: &str =
@@ -57,8 +57,6 @@
     pub build_fingerprint: String,
     /// Interval between collections.
     pub collection_interval: Duration,
-    /// Length of time each collection lasts for.
-    pub sampling_period: Duration,
     /// An optional filter to limit which binaries to or not to profile.
     pub binary_filter: String,
     /// Maximum size of the trace directory.
@@ -75,7 +73,6 @@
                 "collection_interval",
                 600,
             )?),
-            sampling_period: Duration::from_millis(get_device_config("sampling_period", 500)?),
             binary_filter: get_device_config("binary_filter", DEFAULT_BINARY_FILTER.to_string())?,
             max_trace_limit: get_device_config(
                 "max_trace_limit",
@@ -123,6 +120,13 @@
     Ok(T::from_str(&config)?)
 }
 
+pub fn get_sampling_period() -> Duration {
+    let default_period = 500;
+    Duration::from_millis(
+        get_device_config("sampling_period", default_period).unwrap_or(default_period),
+    )
+}
+
 fn get_property<T>(key: &str, default_value: T) -> Result<T>
 where
     T: FromStr + ToString,
diff --git a/profcollectd/libprofcollectd/scheduler.rs b/profcollectd/libprofcollectd/scheduler.rs
index 5558f58..8695f57 100644
--- a/profcollectd/libprofcollectd/scheduler.rs
+++ b/profcollectd/libprofcollectd/scheduler.rs
@@ -25,7 +25,7 @@
 use std::thread;
 use std::time::{Duration, Instant};
 
-use crate::config::{Config, LOG_FILE, PROFILE_OUTPUT_DIR, TRACE_OUTPUT_DIR};
+use crate::config::{get_sampling_period, Config, LOG_FILE, PROFILE_OUTPUT_DIR, TRACE_OUTPUT_DIR};
 use crate::trace_provider::{self, TraceProvider};
 use anyhow::{anyhow, ensure, Context, Result};
 
@@ -73,7 +73,7 @@
                             trace_provider.lock().unwrap().trace(
                                 &TRACE_OUTPUT_DIR,
                                 "periodic",
-                                &config.sampling_period,
+                                &get_sampling_period(),
                                 &config.binary_filter,
                             );
                         }
@@ -100,7 +100,7 @@
             trace_provider.lock().unwrap().trace(
                 &TRACE_OUTPUT_DIR,
                 tag,
-                &config.sampling_period,
+                &get_sampling_period(),
                 &config.binary_filter,
             );
         }
diff --git a/simpleperf/BranchListFile_test.cpp b/simpleperf/BranchListFile_test.cpp
index 759b021..d7f9a6a 100644
--- a/simpleperf/BranchListFile_test.cpp
+++ b/simpleperf/BranchListFile_test.cpp
@@ -20,6 +20,7 @@
 
 using namespace simpleperf;
 
+// @CddTest = 6.1/C-0-2
 TEST(BranchListFile, etm_branch_to_proto_string) {
   std::vector<bool> branch;
   for (size_t i = 0; i < 100; i++) {
diff --git a/simpleperf/CallChainJoiner_test.cpp b/simpleperf/CallChainJoiner_test.cpp
index 90460e0..4b0fa29 100644
--- a/simpleperf/CallChainJoiner_test.cpp
+++ b/simpleperf/CallChainJoiner_test.cpp
@@ -33,6 +33,7 @@
   return tmp_ip == expected_output_ip && tmp_sp == expected_output_sp;
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(LRUCache, different_nodes) {
   LRUCache cache(sizeof(CacheNode) * 2, 1);
   ASSERT_EQ(cache.Stat().max_node_count, 2u);
@@ -65,6 +66,7 @@
   ASSERT_NE(cache.FindNode(1, ip[0], sp2[0]), nullptr);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(LRUCache, extend_chains) {
   // matched_node_count_to_extend_callchain = 1
   // c -> b
@@ -93,6 +95,7 @@
   ASSERT_EQ(cache3.Stat().used_node_count, 4u);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(LRUCache, avoid_ip_sp_loop) {
   LRUCache cache(sizeof(CacheNode) * 2, 1);
   std::vector<uint64_t> ip = {0xa, 0xb};
@@ -104,6 +107,7 @@
   ASSERT_EQ(cache.Stat().recycled_node_count, 0u);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(LRUCache, one_chain) {
   LRUCache cache(sizeof(CacheNode) * 4, 1);
   ASSERT_EQ(cache.Stat().max_node_count, 4u);
@@ -125,6 +129,7 @@
   ASSERT_EQ(cache.Stat().recycled_node_count, 0u);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(LRUCache, many_chains) {
   LRUCache cache(sizeof(CacheNode) * 12, 1);
   // 4 -> 3 -> 2 -> 1
@@ -149,6 +154,7 @@
   ASSERT_EQ(cache.FindNode(0, 0xa, 0xa), nullptr);
 }
 
+// @CddTest = 6.1/C-0-2
 class CallChainJoinerTest : public ::testing::Test {
  protected:
   void SetUp() override {
@@ -164,6 +170,7 @@
   std::unique_ptr<ScopedTempFiles> scoped_temp_files_;
 };
 
+// @CddTest = 6.1/C-0-2
 TEST_F(CallChainJoinerTest, smoke) {
   CallChainJoiner joiner(sizeof(CacheNode) * 1024, 1, true);
   for (pid_t pid = 0; pid < 10; ++pid) {
@@ -230,6 +237,7 @@
   ASSERT_EQ(joiner.GetStat().after_join_max_chain_length, 5u);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(CallChainJoinerTest, no_original_chains) {
   CallChainJoiner joiner(sizeof(CacheNode) * 1024, 1, false);
   ASSERT_TRUE(joiner.AddCallChain(0, 0, CallChainJoiner::ORIGINAL_OFFLINE, {1}, {1}));
@@ -249,6 +257,7 @@
   joiner.DumpStat();
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(CallChainJoinerTest, no_chains) {
   CallChainJoiner joiner(sizeof(CacheNode) * 1024, 1, false);
   ASSERT_TRUE(joiner.JoinCallChains());
diff --git a/simpleperf/ETMConstants.h b/simpleperf/ETMConstants.h
index 78e9cc2..003d88a 100644
--- a/simpleperf/ETMConstants.h
+++ b/simpleperf/ETMConstants.h
@@ -24,6 +24,7 @@
 static constexpr int ETM_OPT_CTXTID2 = 15;
 static constexpr int ETM_OPT_TS = 28;
 // For etm_config_reg:
+static constexpr int ETM4_CFG_BIT_CCI = 4;
 static constexpr int ETM4_CFG_BIT_CTXTID = 6;
 static constexpr int ETM4_CFG_BIT_VMID = 7;
 static constexpr int ETM4_CFG_BIT_TS = 11;
diff --git a/simpleperf/ETMRecorder.cpp b/simpleperf/ETMRecorder.cpp
index cde1eb2..a722df5 100644
--- a/simpleperf/ETMRecorder.cpp
+++ b/simpleperf/ETMRecorder.cpp
@@ -229,6 +229,7 @@
       }
       if (cycles_supported) {
         etm_event_config_ |= 1ULL << ETM_OPT_CYCACC;
+        etm_config_reg_ |= 1U << ETM4_CFG_BIT_CCI;
 
         if (cycle_threshold_) {
           cc_threshold_config_ |= cycle_threshold_;
diff --git a/simpleperf/IOEventLoop_test.cpp b/simpleperf/IOEventLoop_test.cpp
index 74a4528..fbbc0fc 100644
--- a/simpleperf/IOEventLoop_test.cpp
+++ b/simpleperf/IOEventLoop_test.cpp
@@ -26,6 +26,7 @@
 
 using namespace simpleperf;
 
+// @CddTest = 6.1/C-0-2
 TEST(IOEventLoop, read) {
   int fd[2];
   ASSERT_EQ(0, pipe(fd));
@@ -65,6 +66,7 @@
   close(fd[1]);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(IOEventLoop, write) {
   int fd[2];
   ASSERT_EQ(0, pipe(fd));
@@ -101,6 +103,7 @@
   ASSERT_EQ(100, count);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(IOEventLoop, signal) {
   IOEventLoop loop;
   int count = 0;
@@ -147,10 +150,12 @@
   ASSERT_LT(time_used, max_time_in_sec);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(IOEventLoop, periodic) {
   TestPeriodicEvents(1000, 100);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(IOEventLoop, one_time_event) {
   int duration_in_us = 1000;
   timeval tv = {};
@@ -179,6 +184,7 @@
   ASSERT_LT(time_used, max_time_in_sec);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(IOEventLoop, read_and_del_event) {
   int fd[2];
   ASSERT_EQ(0, pipe(fd));
@@ -204,6 +210,7 @@
   close(fd[1]);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(IOEventLoop, disable_enable_event) {
   int fd[2];
   ASSERT_EQ(0, pipe(fd));
@@ -241,6 +248,7 @@
   close(fd[1]);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(IOEventLoop, disable_enable_periodic_event) {
   timeval tv;
   tv.tv_sec = 0;
@@ -267,11 +275,13 @@
   ASSERT_EQ(2u, periodic_count);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(IOEventLoop, exit_before_loop) {
   IOEventLoop loop;
   ASSERT_TRUE(loop.ExitLoop());
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(IOEventLoop, priority) {
   int low_priority_fd[2];
   ASSERT_EQ(0, pipe(low_priority_fd));
diff --git a/simpleperf/JITDebugReader_test.cpp b/simpleperf/JITDebugReader_test.cpp
index d46236a..4aaad81 100644
--- a/simpleperf/JITDebugReader_test.cpp
+++ b/simpleperf/JITDebugReader_test.cpp
@@ -32,6 +32,7 @@
 using namespace simpleperf;
 using namespace simpleperf::JITDebugReader_impl;
 
+// @CddTest = 6.1/C-0-2
 TEST(TempSymFile, smoke) {
   TemporaryFile tmpfile;
   std::unique_ptr<TempSymFile> symfile = TempSymFile::Create(tmpfile.path, false);
@@ -51,6 +52,7 @@
   ASSERT_EQ(strncmp(test_data.c_str(), buf, test_data.size()), 0);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(JITDebugReader, read_dex_file_in_memory) {
   // 1. Create dex file in memory. Use mmap instead of malloc, to avoid the pointer from
   // being modified by memory tag (or pointer authentication?) on ARM64.
diff --git a/simpleperf/MapRecordReader_test.cpp b/simpleperf/MapRecordReader_test.cpp
index 669b31f..d194cb5 100644
--- a/simpleperf/MapRecordReader_test.cpp
+++ b/simpleperf/MapRecordReader_test.cpp
@@ -26,6 +26,7 @@
 
 using namespace simpleperf;
 
+// @CddTest = 6.1/C-0-2
 class MapRecordReaderTest : public ::testing::Test {
  protected:
   bool CreateMapRecordReader() {
@@ -54,12 +55,14 @@
   size_t comm_record_count_ = 0;
 };
 
+// @CddTest = 6.1/C-0-2
 TEST_F(MapRecordReaderTest, ReadKernelMaps) {
   ASSERT_TRUE(CreateMapRecordReader());
   ASSERT_TRUE(reader_->ReadKernelMaps());
   ASSERT_GT(map_record_count_, 0);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(MapRecordReaderTest, ReadProcessMaps) {
   ASSERT_TRUE(CreateMapRecordReader());
   ASSERT_TRUE(reader_->ReadProcessMaps(getpid(), 0));
@@ -67,6 +70,7 @@
   ASSERT_GT(comm_record_count_, 0);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(MapRecordReaderTest, MapRecordThread) {
 #ifdef __ANDROID__
   std::string tmpdir = "/data/local/tmp";
diff --git a/simpleperf/OfflineUnwinder_test.cpp b/simpleperf/OfflineUnwinder_test.cpp
index 7f9d9aa..c13e229 100644
--- a/simpleperf/OfflineUnwinder_test.cpp
+++ b/simpleperf/OfflineUnwinder_test.cpp
@@ -44,6 +44,7 @@
   return true;
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(OfflineUnwinder, UnwindMaps) {
   // 1. Create fake map entries.
   std::unique_ptr<Dso> fake_dso = Dso::CreateDso(DSO_UNKNOWN_FILE, "unknown");
@@ -90,6 +91,7 @@
   ASSERT_TRUE(CheckUnwindMaps(maps, map_set));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(OfflineUnwinder, CollectMetaInfo) {
   std::unordered_map<std::string, std::string> info_map;
   OfflineUnwinder::CollectMetaInfo(&info_map);
@@ -100,6 +102,7 @@
   }
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(OfflineUnwinder, ARM64PackMask) {
   std::unordered_map<std::string, std::string> info_map;
   info_map[OfflineUnwinder::META_KEY_ARM64_PAC_MASK] = "0xff00000000";
diff --git a/simpleperf/ProbeEvents_test.cpp b/simpleperf/ProbeEvents_test.cpp
index be13538..630c576 100644
--- a/simpleperf/ProbeEvents_test.cpp
+++ b/simpleperf/ProbeEvents_test.cpp
@@ -23,6 +23,7 @@
 
 using namespace simpleperf;
 
+// @CddTest = 6.1/C-0-2
 TEST(probe_events, ParseKprobeEventName) {
   ProbeEvent event;
   ASSERT_TRUE(ProbeEvents::ParseKprobeEventName("p:myprobe do_sys_open", &event));
diff --git a/simpleperf/RecordFilter_test.cpp b/simpleperf/RecordFilter_test.cpp
index 3bbda4c..1d5d1a0 100644
--- a/simpleperf/RecordFilter_test.cpp
+++ b/simpleperf/RecordFilter_test.cpp
@@ -30,6 +30,7 @@
 
 using namespace simpleperf;
 
+// @CddTest = 6.1/C-0-2
 class RecordFilterTest : public ::testing::Test {
  public:
   RecordFilterTest() : filter(thread_tree) {}
@@ -58,10 +59,12 @@
   std::unique_ptr<SampleRecord> record;
 };
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordFilterTest, no_filter) {
   ASSERT_TRUE(filter.Check(GetRecord(0, 0)));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordFilterTest, cpu) {
   filter.AddCpus({1});
   SampleRecord& r = GetRecord(0, 0);
@@ -71,18 +74,21 @@
   ASSERT_FALSE(filter.Check(r));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordFilterTest, exclude_pid) {
   filter.AddPids({1}, true);
   ASSERT_FALSE(filter.Check(GetRecord(1, 1)));
   ASSERT_TRUE(filter.Check(GetRecord(2, 2)));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordFilterTest, exclude_tid) {
   filter.AddTids({1}, true);
   ASSERT_FALSE(filter.Check(GetRecord(1, 1)));
   ASSERT_TRUE(filter.Check(GetRecord(1, 2)));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordFilterTest, exclude_process_name_regex) {
   ASSERT_TRUE(filter.AddProcessNameRegex("processA", true));
   thread_tree.SetThreadName(1, 1, "processA1");
@@ -91,6 +97,7 @@
   ASSERT_TRUE(filter.Check(GetRecord(2, 2)));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordFilterTest, exclude_thread_name_regex) {
   ASSERT_TRUE(filter.AddThreadNameRegex("threadA", true));
   thread_tree.SetThreadName(1, 1, "processA_threadA");
@@ -100,6 +107,7 @@
 }
 
 #if defined(__linux__)
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordFilterTest, exclude_uid) {
   pid_t pid = getpid();
   std::optional<uint32_t> uid = GetProcessUid(pid);
@@ -112,18 +120,21 @@
 }
 #endif  // defined(__linux__)
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordFilterTest, include_pid) {
   filter.AddPids({1}, false);
   ASSERT_TRUE(filter.Check(GetRecord(1, 1)));
   ASSERT_FALSE(filter.Check(GetRecord(2, 2)));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordFilterTest, include_tid) {
   filter.AddTids({1}, false);
   ASSERT_TRUE(filter.Check(GetRecord(1, 1)));
   ASSERT_FALSE(filter.Check(GetRecord(1, 2)));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordFilterTest, include_process_name_regex) {
   ASSERT_TRUE(filter.AddProcessNameRegex("processA", false));
   thread_tree.SetThreadName(1, 1, "processA1");
@@ -132,6 +143,7 @@
   ASSERT_FALSE(filter.Check(GetRecord(2, 2)));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordFilterTest, include_thread_name_regex) {
   ASSERT_TRUE(filter.AddThreadNameRegex("threadA", false));
   thread_tree.SetThreadName(1, 1, "processA_threadA");
@@ -141,6 +153,7 @@
 }
 
 #if defined(__linux__)
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordFilterTest, include_uid) {
   pid_t pid = getpid();
   std::optional<uint32_t> uid = GetProcessUid(pid);
@@ -152,6 +165,7 @@
 }
 #endif  // defined(__linux__)
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordFilterTest, global_time_filter) {
   ASSERT_TRUE(
       SetFilterData("GLOBAL_BEGIN 1000\n"
@@ -179,6 +193,7 @@
   ASSERT_FALSE(filter.Check(r));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordFilterTest, process_time_filter) {
   ASSERT_TRUE(
       SetFilterData("PROCESS_BEGIN 1 1000\n"
@@ -202,6 +217,7 @@
   ASSERT_FALSE(filter.Check(r));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordFilterTest, thread_time_filter) {
   ASSERT_TRUE(
       SetFilterData("THREAD_BEGIN 1 1000\n"
@@ -225,6 +241,7 @@
   ASSERT_FALSE(filter.Check(r));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordFilterTest, clock_in_time_filter) {
   // If there is no filter data, any clock is fine.
   ASSERT_TRUE(filter.CheckClock("monotonic"));
@@ -239,6 +256,7 @@
   ASSERT_FALSE(filter.CheckClock("monotonic"));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordFilterTest, error_in_time_filter) {
   // no timestamp error
   ASSERT_FALSE(SetFilterData("GLOBAL_BEGIN"));
@@ -290,6 +308,7 @@
 
 }  // namespace
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordFilterTest, parse_options) {
   ParseRecordFilterCommand filter_cmd(filter);
 
diff --git a/simpleperf/RecordReadThread_test.cpp b/simpleperf/RecordReadThread_test.cpp
index e597e44..2ff9a46 100644
--- a/simpleperf/RecordReadThread_test.cpp
+++ b/simpleperf/RecordReadThread_test.cpp
@@ -32,6 +32,7 @@
 
 using namespace simpleperf;
 
+// @CddTest = 6.1/C-0-2
 class RecordBufferTest : public ::testing::Test {
  protected:
   void PushRecord(uint32_t type, size_t size) {
@@ -57,6 +58,7 @@
   std::unique_ptr<RecordBuffer> buffer_;
 };
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordBufferTest, fifo) {
   for (size_t loop = 0; loop < 10; ++loop) {
     buffer_.reset(new RecordBuffer(sizeof(perf_event_header) * 10));
@@ -73,6 +75,7 @@
   }
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(RecordParser, smoke) {
   std::unique_ptr<RecordFileReader> reader =
       RecordFileReader::CreateInstance(GetTestData(PERF_DATA_NO_UNWIND));
@@ -113,6 +116,7 @@
   }));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(RecordParser, GetStackSizePos_with_PerfSampleReadType) {
   const EventType* type = FindEventTypeByName("cpu-clock");
   ASSERT_TRUE(type != nullptr);
@@ -190,6 +194,7 @@
   };
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(KernelRecordReader, smoke) {
   // 1. Create fake records.
   perf_event_attr attr = CreateFakeEventAttr();
@@ -229,6 +234,7 @@
   ASSERT_FALSE(reader.MoveToNextRecord(parser));
 }
 
+// @CddTest = 6.1/C-0-2
 class RecordReadThreadTest : public ::testing::Test {
  protected:
   std::vector<EventFd*> CreateFakeEventFds(const perf_event_attr& attr, size_t event_fd_count) {
@@ -270,6 +276,7 @@
   std::vector<std::unique_ptr<MockEventFd>> event_fds_;
 };
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordReadThreadTest, handle_cmds) {
   perf_event_attr attr = CreateFakeEventAttr();
   records_ = CreateFakeRecords(attr, 2, 0, 0);
@@ -291,6 +298,7 @@
   ASSERT_TRUE(thread.StopReadThread());
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordReadThreadTest, read_records) {
   perf_event_attr attr = CreateFakeEventAttr();
   RecordReadThread thread(128 * 1024, attr, 1, 1, 0);
@@ -323,6 +331,7 @@
   }
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordReadThreadTest, process_sample_record) {
   perf_event_attr attr = CreateFakeEventAttr();
   attr.sample_type |= PERF_SAMPLE_STACK_USER;
@@ -377,6 +386,7 @@
 
 // Test that the data notification exists until the RecordBuffer is empty. So we can read all
 // records even if reading one record at a time.
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordReadThreadTest, has_data_notification_until_buffer_empty) {
   perf_event_attr attr = CreateFakeEventAttr();
   RecordReadThread thread(128 * 1024, attr, 1, 1, 0);
@@ -403,6 +413,7 @@
   ASSERT_TRUE(thread.RemoveEventFds(event_fds));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordReadThreadTest, no_truncated_samples) {
   perf_event_attr attr = CreateFakeEventAttr();
   attr.sample_type |= PERF_SAMPLE_STACK_USER;
@@ -426,6 +437,7 @@
   ASSERT_EQ(thread.GetStat().userspace_truncated_stack_samples, 0u);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordReadThreadTest, exclude_perf) {
   perf_event_attr attr = CreateFakeEventAttr();
   attr.sample_type |= PERF_SAMPLE_STACK_USER;
@@ -475,6 +487,7 @@
       : buf1(buf1_size, c), buf2(buf2_size, c), pad(pad_size, 0), lost(lost) {}
 };
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordReadThreadTest, read_aux_data) {
   ScopedEventTypes scoped_types("cs-etm,0,0");
   const EventType* type = FindEventTypeByName("cs-etm");
@@ -569,4 +582,4 @@
   }
   ASSERT_EQ(aux_data_size, thread.GetStat().aux_data_size);
   ASSERT_EQ(lost_aux_data_size, thread.GetStat().lost_aux_data_size);
-}
\ No newline at end of file
+}
diff --git a/simpleperf/RegEx_test.cpp b/simpleperf/RegEx_test.cpp
index cbb25ae..978772c 100644
--- a/simpleperf/RegEx_test.cpp
+++ b/simpleperf/RegEx_test.cpp
@@ -20,6 +20,7 @@
 
 using namespace simpleperf;
 
+// @CddTest = 6.1/C-0-2
 TEST(RegEx, smoke) {
   auto re = RegEx::Create("b+");
   ASSERT_EQ(re->GetPattern(), "b+");
@@ -42,6 +43,7 @@
   ASSERT_EQ(re->Replace("ababb", "c").value(), "acac");
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(RegEx, invalid_pattern) {
   ASSERT_TRUE(RegEx::Create("?hello") == nullptr);
 }
diff --git a/simpleperf/cmd_api_test.cpp b/simpleperf/cmd_api_test.cpp
index 41a2a16..d1fb044 100644
--- a/simpleperf/cmd_api_test.cpp
+++ b/simpleperf/cmd_api_test.cpp
@@ -90,6 +90,7 @@
 
 #endif  // defined(__ANDROID__)
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_api, java_app) {
 #if defined(__ANDROID__)
   RecordApp("simpleperf.demo.java_api", GetTestData("java_api.apk"));
@@ -98,10 +99,11 @@
 #endif
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_api, native_app) {
 #if defined(__ANDROID__)
   RecordApp("simpleperf.demo.cpp_api", GetTestData("cpp_api.apk"));
 #else
   GTEST_LOG_(INFO) << "This test tests recording apps on Android.";
 #endif
-}
\ No newline at end of file
+}
diff --git a/simpleperf/cmd_boot_record_test.cpp b/simpleperf/cmd_boot_record_test.cpp
index 25b2aff..73266ce 100644
--- a/simpleperf/cmd_boot_record_test.cpp
+++ b/simpleperf/cmd_boot_record_test.cpp
@@ -28,6 +28,7 @@
   return CreateCommandInstance("boot-record");
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_boot_record, smoke) {
   TEST_REQUIRE_ROOT();
   ASSERT_TRUE(BootRecordCmd()->Run({"--enable", "-a -g --duration 1"}));
diff --git a/simpleperf/cmd_debug_unwind_test.cpp b/simpleperf/cmd_debug_unwind_test.cpp
index d0bbfe8..2bf14a5 100644
--- a/simpleperf/cmd_debug_unwind_test.cpp
+++ b/simpleperf/cmd_debug_unwind_test.cpp
@@ -35,6 +35,7 @@
   return CreateCommandInstance("debug-unwind");
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_debug_unwind, unwind_sample_option) {
   std::string input_data = GetTestData(PERF_DATA_NO_UNWIND);
   CaptureStdout capture;
@@ -44,6 +45,7 @@
   ASSERT_NE(capture.Finish().find("sample_time: 1516379654300997"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_debug_unwind, sample_time_option) {
   std::string input_data = GetTestData(PERF_DATA_NO_UNWIND);
   CaptureStdout capture;
@@ -58,6 +60,7 @@
   ASSERT_NE(output.find("sample_time: 1516379655959122"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_debug_unwind, output_option) {
   std::string input_data = GetTestData(PERF_DATA_NO_UNWIND);
   TemporaryFile tmpfile;
@@ -69,6 +72,7 @@
   ASSERT_NE(output.find("sample_time: 1516379654300997"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_debug_unwind, symfs_option) {
   std::string input_data = GetTestData(NATIVELIB_IN_APK_PERF_DATA);
   CaptureStdout capture;
@@ -80,6 +84,7 @@
             std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_debug_unwind, unwind_with_ip_zero_in_callchain) {
   CaptureStdout capture;
   ASSERT_TRUE(capture.Start());
@@ -88,6 +93,7 @@
   ASSERT_NE(capture.Finish().find("sample_time: 152526249937103"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_debug_unwind, unwind_embedded_lib_in_apk) {
   // Check if we can unwind through a native library embedded in an apk. In the profiling data
   // file, there is a sample with ip address pointing to
@@ -107,6 +113,7 @@
   ASSERT_NE(output.find("dso_2: /bionic/lib64/libc.so"), std::string::npos) << output;
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_debug_unwind, unwind_sample_in_unwinding_debug_info_file) {
   CaptureStdout capture;
   ASSERT_TRUE(capture.Start());
@@ -116,6 +123,7 @@
   ASSERT_NE(output.find("symbol_5: android.os.Handler.post"), std::string::npos) << output;
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_debug_unwind, skip_sample_print_option) {
   std::string input_data = GetTestData(PERF_DATA_NO_UNWIND);
   CaptureStdout capture;
@@ -128,6 +136,7 @@
   ASSERT_NE(output.find("unwinding_sample_count: 8"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_debug_unwind, generate_test_file) {
   TemporaryFile tmpfile;
   close(tmpfile.release());
@@ -143,6 +152,7 @@
   ASSERT_NE(output.find("symbol_2: android.os.Handler.enqueueMessage"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_debug_unwind, generate_test_file_with_build_id) {
   TemporaryFile tmpfile;
   close(tmpfile.release());
@@ -157,6 +167,7 @@
   ASSERT_STREQ(build_ids[0].filename, "/apex/com.android.runtime/lib64/bionic/libc.so");
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_debug_unwind, generate_report) {
   TemporaryFile tmpfile;
   close(tmpfile.release());
@@ -169,6 +180,7 @@
   ASSERT_NE(output.find("symbol_2: android.os.Handler.enqueueMessage"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_debug_unwind, unwind_sample_for_small_map_range) {
   CaptureStdout capture;
   ASSERT_TRUE(capture.Start());
diff --git a/simpleperf/cmd_dumprecord_test.cpp b/simpleperf/cmd_dumprecord_test.cpp
index e6cc5e2..ffdcbc2 100644
--- a/simpleperf/cmd_dumprecord_test.cpp
+++ b/simpleperf/cmd_dumprecord_test.cpp
@@ -26,22 +26,27 @@
   return CreateCommandInstance("dump");
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_dump, record_file_option) {
   ASSERT_TRUE(DumpCmd()->Run({GetTestData("perf.data")}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_dump, input_option) {
   ASSERT_TRUE(DumpCmd()->Run({"-i", GetTestData("perf.data")}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_dump, dump_data_generated_by_linux_perf) {
   ASSERT_TRUE(DumpCmd()->Run({GetTestData(PERF_DATA_GENERATED_BY_LINUX_PERF)}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_dump, dump_callchain_records) {
   ASSERT_TRUE(DumpCmd()->Run({GetTestData(PERF_DATA_WITH_CALLCHAIN_RECORD)}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_dump, dump_callchain_of_sample_records) {
   CaptureStdout capture;
   ASSERT_TRUE(capture.Start());
@@ -51,6 +56,7 @@
   ASSERT_NE(data.find("__ioctl (/system/lib64/libc.so[+70b6c])"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_dump, dump_tracepoint_fields_of_sample_records) {
   CaptureStdout capture;
   ASSERT_TRUE(capture.Start());
@@ -66,6 +72,7 @@
             std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_dump, etm_data) {
   CaptureStdout capture;
   ASSERT_TRUE(capture.Start());
@@ -78,6 +85,7 @@
   ASSERT_NE(data.find("OCSD_GEN_TRC_ELEM_INSTR_RANGE"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_dump, dump_arm_regs_recorded_in_arm64) {
   ASSERT_TRUE(DumpCmd()->Run({GetTestData("perf_with_arm_regs.data")}));
 }
diff --git a/simpleperf/cmd_inject_test.cpp b/simpleperf/cmd_inject_test.cpp
index 9bb1efb..b6e6456 100644
--- a/simpleperf/cmd_inject_test.cpp
+++ b/simpleperf/cmd_inject_test.cpp
@@ -59,6 +59,7 @@
   ASSERT_EQ(data, expected_data);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_inject, smoke) {
   std::string data;
   ASSERT_TRUE(RunInjectCmd({}, &data));
@@ -67,6 +68,7 @@
   CheckMatchingExpectedData("perf_inject.data", data);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_inject, binary_option) {
   // Test that data for etm_test_loop is generated when selected by --binary.
   std::string data;
@@ -86,10 +88,12 @@
   ASSERT_EQ(data.find("etm_test_loop"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_inject, exclude_perf_option) {
   ASSERT_TRUE(RunInjectCmd({"--exclude-perf"}, nullptr));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_inject, output_option) {
   TemporaryFile tmpfile;
   close(tmpfile.release());
@@ -100,6 +104,7 @@
   CheckMatchingExpectedData("perf_inject.data", autofdo_data);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_inject, skip_empty_output_file) {
   TemporaryFile tmpfile;
   close(tmpfile.release());
@@ -110,6 +115,7 @@
   tmpfile.DoNotRemove();
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_inject, inject_kernel_data) {
   const std::string recording_file =
       GetTestData(std::string("etm") + OS_PATH_SEPARATOR + "perf_kernel.data");
@@ -132,6 +138,7 @@
   ASSERT_EQ(output, autofdo_output);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_inject, unformatted_trace) {
   std::string data;
   std::string perf_with_unformatted_trace =
@@ -142,6 +149,7 @@
   CheckMatchingExpectedData("perf_inject.data", data);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_inject, multiple_input_files) {
   std::string data;
   std::string perf_data = GetTestData(PERF_DATA_ETM_TEST_LOOP);
@@ -165,6 +173,7 @@
   ASSERT_NE(data.find("106c->1074:200"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_inject, merge_branch_list_files) {
   TemporaryFile tmpfile;
   close(tmpfile.release());
@@ -178,6 +187,7 @@
   ASSERT_NE(autofdo_data.find("106c->1074:200"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_inject, report_warning_when_overflow) {
   CapturedStderr capture;
   std::vector<std::unique_ptr<TemporaryFile>> branch_list_files;
@@ -217,6 +227,7 @@
   ASSERT_NE(autofdo_data.find("106c->1074:18446744073709551615"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_inject, accept_missing_aux_data) {
   // Recorded with "-e cs-etm:u --user-buffer-size 64k sleep 1".
   std::string perf_data = GetTestData("etm/perf_with_missing_aux_data.data");
@@ -225,6 +236,7 @@
   ASSERT_TRUE(RunInjectCmd({"--output", "branch-list", "-i", perf_data, "-o", tmpfile.path}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_inject, read_lbr_data) {
   // Convert perf.data to AutoFDO text format.
   std::string perf_data_path = GetTestData("lbr/perf_lbr.data");
@@ -264,6 +276,7 @@
   ASSERT_NE(data.find("194d->1940:706"), data.npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_inject, inject_small_binary) {
   // etm_test_loop_small, a binary compiled with
   // "-Wl,-z,noseparate-code", where the file is smaller than its text
diff --git a/simpleperf/cmd_kmem_test.cpp b/simpleperf/cmd_kmem_test.cpp
index b34f614..7c66be4 100644
--- a/simpleperf/cmd_kmem_test.cpp
+++ b/simpleperf/cmd_kmem_test.cpp
@@ -85,15 +85,18 @@
   return KmemCmd()->Run(v);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(kmem_cmd, record_slab) {
   TEST_IN_ROOT(ASSERT_TRUE(RunKmemRecordCmd({"--slab"})));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(kmem_cmd, record_fp_callchain_sampling) {
   TEST_IN_ROOT(ASSERT_TRUE(RunKmemRecordCmd({"--slab", "-g"})));
   TEST_IN_ROOT(ASSERT_TRUE(RunKmemRecordCmd({"--slab", "--call-graph", "fp"})));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(kmem_cmd, record_and_report) {
   TemporaryFile tmp_file;
   TEST_IN_ROOT({
@@ -104,6 +107,7 @@
   });
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(kmem_cmd, record_and_report_callgraph) {
   TemporaryFile tmp_file;
   TEST_IN_ROOT({
@@ -116,6 +120,7 @@
 
 #endif
 
+// @CddTest = 6.1/C-0-2
 TEST(kmem_cmd, report) {
   ReportResult result;
   KmemReportFile(PERF_DATA_WITH_KMEM_SLAB_CALLGRAPH_RECORD, {}, &result);
@@ -124,6 +129,7 @@
   ASSERT_NE(result.content.find("__alloc_skb"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(kmem_cmd, report_all_sort_options) {
   ReportResult result;
   KmemReportFile(
@@ -134,6 +140,7 @@
   ASSERT_NE(result.content.find("GfpFlags"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(kmem_cmd, report_callgraph) {
   ReportResult result;
   KmemReportFile(PERF_DATA_WITH_KMEM_SLAB_CALLGRAPH_RECORD, {"-g"}, &result);
diff --git a/simpleperf/cmd_list.cpp b/simpleperf/cmd_list.cpp
index 963259d..926b7f7 100644
--- a/simpleperf/cmd_list.cpp
+++ b/simpleperf/cmd_list.cpp
@@ -246,8 +246,8 @@
 }
 
 static bool IsEventTypeSupported(const EventType& event_type) {
-  // Because PMU events are provided by kernel, we assume it's supported.
-  if (event_type.IsPmuEvent()) {
+  // PMU and tracepoint events are provided by kernel. So we assume they're supported.
+  if (event_type.IsPmuEvent() || event_type.IsTracepointEvent()) {
     return true;
   }
   perf_event_attr attr = CreateDefaultPerfEventAttr(event_type);
diff --git a/simpleperf/cmd_list_test.cpp b/simpleperf/cmd_list_test.cpp
index e2f804d..940f759 100644
--- a/simpleperf/cmd_list_test.cpp
+++ b/simpleperf/cmd_list_test.cpp
@@ -21,6 +21,7 @@
 
 using namespace simpleperf;
 
+// @CddTest = 6.1/C-0-2
 class ListCommandTest : public ::testing::Test {
  protected:
   virtual void SetUp() {
@@ -31,22 +32,27 @@
   std::unique_ptr<Command> list_cmd;
 };
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ListCommandTest, no_options) {
   ASSERT_TRUE(list_cmd->Run({}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ListCommandTest, one_option) {
   ASSERT_TRUE(list_cmd->Run({"sw"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ListCommandTest, multiple_options) {
   ASSERT_TRUE(list_cmd->Run({"hw", "tracepoint"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ListCommandTest, show_features_option) {
   ASSERT_TRUE(list_cmd->Run({"--show-features"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ListCommandTest, pmu_option) {
   ASSERT_TRUE(list_cmd->Run({"pmu"}));
 }
diff --git a/simpleperf/cmd_merge_test.cpp b/simpleperf/cmd_merge_test.cpp
index 482d089..1a60c50 100644
--- a/simpleperf/cmd_merge_test.cpp
+++ b/simpleperf/cmd_merge_test.cpp
@@ -46,6 +46,7 @@
   return data;
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(merge_cmd, input_output_options) {
   // missing arguments
   ASSERT_FALSE(MergeCmd()->Run({}));
@@ -63,6 +64,7 @@
   ASSERT_TRUE(MergeCmd()->Run({"-i", input_file, "-i", input_file, "-o", tmpfile.path}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(merge_cmd, merge_two_files) {
   std::string input_file1 = GetTestData("perf_merge1.data");
   std::string input_file2 = GetTestData("perf_merge2.data");
diff --git a/simpleperf/cmd_monitor_test.cpp b/simpleperf/cmd_monitor_test.cpp
index 963a980..8264c96 100644
--- a/simpleperf/cmd_monitor_test.cpp
+++ b/simpleperf/cmd_monitor_test.cpp
@@ -59,15 +59,18 @@
   return (result ? ::testing::AssertionSuccess() : ::testing::AssertionFailure());
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(monitor_cmd, no_options) {
   std::string output;
   ASSERT_FALSE(RunMonitorCmd({}, output));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(monitor_cmd, no_event) {
   ASSERT_FALSE(MonitorCmd()->Run({"-a", "--duration", "1"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(monitor_cmd, global) {
   TEST_REQUIRE_ROOT();
   std::string output;
@@ -75,6 +78,7 @@
   ASSERT_GT(output.size(), 0);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(monitor_cmd, no_perf) {
   TEST_REQUIRE_ROOT();
   std::string output;
@@ -82,6 +86,7 @@
   ASSERT_GT(output.size(), 0);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(monitor_cmd, with_callchain) {
   TEST_REQUIRE_ROOT();
   std::string output;
@@ -89,6 +94,7 @@
   ASSERT_GT(output.size(), 0);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(monitor_cmd, with_callchain_fp) {
   TEST_REQUIRE_ROOT();
   std::string output;
@@ -96,6 +102,7 @@
   ASSERT_GT(output.size(), 0);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(monitor_cmd, with_callchain_dwarf) {
   TEST_REQUIRE_ROOT();
   std::string output;
@@ -103,18 +110,21 @@
   ASSERT_GT(output.size(), 0);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(monitor_cmd, frequency) {
   TEST_REQUIRE_ROOT();
   std::string output;
   ASSERT_TRUE(RunMonitorCmd({"-a", "-f", "1"}, output));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(monitor_cmd, count) {
   TEST_REQUIRE_ROOT();
   std::string output;
   ASSERT_TRUE(RunMonitorCmd({"-a", "-c", "10000000"}, output));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(monitor_cmd, cpu_percent) {
   TEST_REQUIRE_ROOT();
   std::string output;
@@ -124,6 +134,7 @@
   ASSERT_FALSE(RunMonitorCmd({"-a", "--cpu-percent", "101"}, output));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(monitor_cmd, record_filter_options) {
   TEST_REQUIRE_ROOT();
   std::string output;
diff --git a/simpleperf/cmd_record_test.cpp b/simpleperf/cmd_record_test.cpp
index 345a128..131f6da 100644
--- a/simpleperf/cmd_record_test.cpp
+++ b/simpleperf/cmd_record_test.cpp
@@ -85,10 +85,12 @@
   return RecordCmd()->Run(v);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, no_options) {
   ASSERT_TRUE(RunRecordCmd({}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, system_wide_option) {
   TEST_IN_ROOT(ASSERT_TRUE(RunRecordCmd({"-a"})));
 }
@@ -115,16 +117,19 @@
   FAIL();
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, sample_period_option) {
   TemporaryFile tmpfile;
   ASSERT_TRUE(RunRecordCmd({"-c", "100000"}, tmpfile.path));
   CheckEventType(tmpfile.path, GetDefaultEvent(), 100000u, 0);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, event_option) {
   ASSERT_TRUE(RunRecordCmd({"-e", "cpu-clock"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, freq_option) {
   TemporaryFile tmpfile;
   ASSERT_TRUE(RunRecordCmd({"-f", "99"}, tmpfile.path));
@@ -134,6 +139,7 @@
   ASSERT_FALSE(RunRecordCmd({"-f", std::to_string(UINT_MAX)}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, multiple_freq_or_sample_period_option) {
   TemporaryFile tmpfile;
   ASSERT_TRUE(RunRecordCmd({"-f", "99", "-e", "task-clock", "-c", "1000000", "-e", "cpu-clock"},
@@ -142,11 +148,13 @@
   CheckEventType(tmpfile.path, "cpu-clock", 1000000u, 0u);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, output_file_option) {
   TemporaryFile tmpfile;
   ASSERT_TRUE(RecordCmd()->Run({"-o", tmpfile.path, "-e", GetDefaultEvent(), "sleep", SLEEP_SEC}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, dump_kernel_mmap) {
   TemporaryFile tmpfile;
   ASSERT_TRUE(RunRecordCmd({}, tmpfile.path));
@@ -167,6 +175,7 @@
   ASSERT_TRUE(have_kernel_mmap);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, dump_build_id_feature) {
   TemporaryFile tmpfile;
   ASSERT_TRUE(RunRecordCmd({}, tmpfile.path));
@@ -177,10 +186,12 @@
   ASSERT_GT(reader->FeatureSectionDescriptors().size(), 0u);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, tracepoint_event) {
   TEST_IN_ROOT(ASSERT_TRUE(RunRecordCmd({"-a", "-e", "sched:sched_switch"})));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, rN_event) {
   TEST_REQUIRE_HW_COUNTER();
   OMIT_TEST_ON_NON_NATIVE_ABIS();
@@ -211,6 +222,7 @@
   ASSERT_EQ(event_number, attrs[0].attr.config);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, branch_sampling) {
   TEST_REQUIRE_HW_COUNTER();
   if (IsBranchSamplingSupported()) {
@@ -225,14 +237,17 @@
   }
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, event_modifier) {
   ASSERT_TRUE(RunRecordCmd({"-e", GetDefaultEvent() + std::string(":u")}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, fp_callchain_sampling) {
   ASSERT_TRUE(RunRecordCmd({"--call-graph", "fp"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, fp_callchain_sampling_warning_on_arm) {
   if (GetTargetArch() != ARCH_ARM) {
     GTEST_LOG_(INFO) << "This test does nothing as it only tests on arm arch.";
@@ -245,10 +260,12 @@
       testing::ExitedWithCode(0), "doesn't work well on arm");
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, system_wide_fp_callchain_sampling) {
   TEST_IN_ROOT(ASSERT_TRUE(RunRecordCmd({"-a", "--call-graph", "fp"})));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, dwarf_callchain_sampling) {
   OMIT_TEST_ON_NON_NATIVE_ABIS();
   ASSERT_TRUE(IsDwarfCallChainSamplingSupported());
@@ -270,12 +287,14 @@
   }
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, system_wide_dwarf_callchain_sampling) {
   OMIT_TEST_ON_NON_NATIVE_ABIS();
   ASSERT_TRUE(IsDwarfCallChainSamplingSupported());
   TEST_IN_ROOT(RunRecordCmd({"-a", "--call-graph", "dwarf"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, no_unwind_option) {
   OMIT_TEST_ON_NON_NATIVE_ABIS();
   ASSERT_TRUE(IsDwarfCallChainSamplingSupported());
@@ -283,6 +302,7 @@
   ASSERT_FALSE(RunRecordCmd({"--no-unwind"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, post_unwind_option) {
   OMIT_TEST_ON_NON_NATIVE_ABIS();
   ASSERT_TRUE(IsDwarfCallChainSamplingSupported());
@@ -294,6 +314,7 @@
   ASSERT_TRUE(RunRecordCmd({"-p", pid, "--call-graph", "dwarf", "--post-unwind=no"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, existing_processes) {
   std::vector<std::unique_ptr<Workload>> workloads;
   CreateProcesses(2, &workloads);
@@ -302,6 +323,7 @@
   ASSERT_TRUE(RunRecordCmd({"-p", pid_list}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, existing_threads) {
   std::vector<std::unique_ptr<Workload>> workloads;
   CreateProcesses(2, &workloads);
@@ -311,17 +333,20 @@
   ASSERT_TRUE(RunRecordCmd({"-t", tid_list}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, no_monitored_threads) {
   TemporaryFile tmpfile;
   ASSERT_FALSE(RecordCmd()->Run({"-o", tmpfile.path}));
   ASSERT_FALSE(RecordCmd()->Run({"-o", tmpfile.path, ""}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, more_than_one_event_types) {
   ASSERT_TRUE(RunRecordCmd({"-e", "task-clock,cpu-clock"}));
   ASSERT_TRUE(RunRecordCmd({"-e", "task-clock", "-e", "cpu-clock"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, mmap_page_option) {
   ASSERT_TRUE(RunRecordCmd({"-m", "1"}));
   ASSERT_FALSE(RunRecordCmd({"-m", "0"}));
@@ -345,6 +370,7 @@
   *success = true;
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, kernel_symbol) {
   TemporaryFile tmpfile;
   ASSERT_TRUE(RunRecordCmd({"--no-dump-symbols"}, tmpfile.path));
@@ -390,6 +416,7 @@
   return true;
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, no_dump_symbols) {
   TemporaryFile tmpfile;
   ASSERT_TRUE(RunRecordCmd({}, tmpfile.path));
@@ -408,6 +435,7 @@
   ASSERT_TRUE(CheckDumpedSymbols(tmpfile.path, false));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, dump_kernel_symbols) {
   TEST_REQUIRE_ROOT();
   TemporaryFile tmpfile;
@@ -423,6 +451,7 @@
   ASSERT_TRUE(has_kernel_symbols);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, group_option) {
   ASSERT_TRUE(RunRecordCmd({"--group", "task-clock,cpu-clock", "-m", "16"}));
   ASSERT_TRUE(
@@ -430,10 +459,12 @@
                     "--group", "task-clock:k,cpu-clock:k", "-m", "16"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, symfs_option) {
   ASSERT_TRUE(RunRecordCmd({"--symfs", "/"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, duration_option) {
   TemporaryFile tmpfile;
   ASSERT_TRUE(RecordCmd()->Run({"--duration", "1.2", "-p", std::to_string(getpid()), "-o",
@@ -442,6 +473,7 @@
       {"--duration", "1", "-o", tmpfile.path, "-e", GetDefaultEvent(), "sleep", "2"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, support_modifier_for_clock_events) {
   for (const std::string& e : {"cpu-clock", "task-clock"}) {
     for (const std::string& m : {"u", "k"}) {
@@ -450,6 +482,7 @@
   }
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, handle_SIGHUP) {
   TemporaryFile tmpfile;
   int pipefd[2];
@@ -470,6 +503,7 @@
   ASSERT_STREQ(data, "STARTED");
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, stop_when_no_more_targets) {
   TemporaryFile tmpfile;
   std::atomic<int> tid(0);
@@ -484,6 +518,7 @@
       {"-o", tmpfile.path, "-t", std::to_string(tid), "--in-app", "-e", GetDefaultEvent()}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, donot_stop_when_having_targets) {
   std::vector<std::unique_ptr<Workload>> workloads;
   CreateProcesses(1, &workloads);
@@ -496,6 +531,7 @@
   ASSERT_GT(end_time_in_ns - start_time_in_ns, static_cast<uint64_t>(2e9));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, start_profiling_fd_option) {
   int pipefd[2];
   ASSERT_EQ(0, pipe(pipefd));
@@ -514,6 +550,7 @@
   ASSERT_EQ("STARTED", s);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, record_meta_info_feature) {
   TemporaryFile tmpfile;
   ASSERT_TRUE(RunRecordCmd({}, tmpfile.path));
@@ -530,6 +567,7 @@
 }
 
 // See http://b/63135835.
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, cpu_clock_for_a_long_time) {
   std::vector<std::unique_ptr<Workload>> workloads;
   CreateProcesses(1, &workloads);
@@ -539,6 +577,7 @@
       RecordCmd()->Run({"-e", "cpu-clock", "-o", tmpfile.path, "-p", pid, "--duration", "3"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, dump_regs_for_tracepoint_events) {
   TEST_REQUIRE_HOST_ROOT();
   TEST_REQUIRE_TRACEPOINT_EVENTS();
@@ -549,6 +588,7 @@
   ASSERT_TRUE(IsDumpingRegsForTracepointEventsSupported());
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, trace_offcpu_option) {
   // On linux host, we need root privilege to read tracepoint events.
   TEST_REQUIRE_HOST_ROOT();
@@ -574,10 +614,12 @@
   ASSERT_FALSE(RunRecordCmd({"--trace-offcpu", "-e", "cpu-clock,task-clock"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, exit_with_parent_option) {
   ASSERT_TRUE(RunRecordCmd({"--exit-with-parent"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, use_cmd_exit_code_option) {
   TemporaryFile tmpfile;
   int exit_code;
@@ -590,6 +632,7 @@
   ASSERT_NE(exit_code, 0);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, clockid_option) {
   if (!IsSettingClockIdSupported()) {
     ASSERT_FALSE(RunRecordCmd({"--clockid", "monotonic"}));
@@ -603,6 +646,7 @@
   }
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, generate_samples_by_hw_counters) {
   TEST_REQUIRE_HW_COUNTER();
   std::vector<std::string> events = {"cpu-cycles", "instructions"};
@@ -622,16 +666,19 @@
   }
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, callchain_joiner_options) {
   ASSERT_TRUE(RunRecordCmd({"--no-callchain-joiner"}));
   ASSERT_TRUE(RunRecordCmd({"--callchain-joiner-min-matching-nodes", "2"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, dashdash) {
   TemporaryFile tmpfile;
   ASSERT_TRUE(RecordCmd()->Run({"-o", tmpfile.path, "-e", GetDefaultEvent(), "--", "sleep", "1"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, size_limit_option) {
   std::vector<std::unique_ptr<Workload>> workloads;
   CreateProcesses(1, &workloads);
@@ -646,6 +693,7 @@
   ASSERT_FALSE(RunRecordCmd({"--size-limit", "0"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, support_mmap2) {
   // mmap2 is supported in kernel >= 3.16. If not supported, please cherry pick below kernel
   // patches:
@@ -654,6 +702,7 @@
   ASSERT_TRUE(IsMmap2Supported());
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, kernel_bug_making_zero_dyn_size) {
   // Test a kernel bug that makes zero dyn_size in kernel < 3.13. If it fails, please cherry pick
   // below kernel patch: 0a196848ca365e perf: Fix arch_perf_out_copy_user default
@@ -680,6 +729,7 @@
   ASSERT_TRUE(has_sample);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, kernel_bug_making_zero_dyn_size_for_kernel_samples) {
   // Test a kernel bug that makes zero dyn_size for syscalls of 32-bit applications in 64-bit
   // kernels. If it fails, please cherry pick below kernel patch:
@@ -709,6 +759,7 @@
   ASSERT_TRUE(has_sample);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, cpu_percent_option) {
   ASSERT_TRUE(RunRecordCmd({"--cpu-percent", "50"}));
   ASSERT_FALSE(RunRecordCmd({"--cpu-percent", "0"}));
@@ -741,6 +792,11 @@
     };
     ProcessSymbolsInPerfDataFile(GetDataPath(), callback);
     if (!success) {
+      if (IsInEmulator() && !HasSample()) {
+        // In emulator, the monitored app may not have a chance to run.
+        GTEST_LOG_(INFO) << "No samples are recorded. Skip checking symbols.";
+        return true;
+      }
       DumpData();
     }
     return success;
@@ -751,6 +807,24 @@
   std::string GetDataPath() const { return perf_data_file_.path; }
 
  private:
+  bool HasSample() {
+    std::unique_ptr<RecordFileReader> reader = RecordFileReader::CreateInstance(GetDataPath());
+    if (!reader) {
+      return false;
+    }
+    bool has_sample = false;
+    auto process_record = [&](std::unique_ptr<Record> r) {
+      if (r->type() == PERF_RECORD_SAMPLE) {
+        has_sample = true;
+      }
+      return true;
+    };
+    if (!reader->ReadDataSection(process_record)) {
+      return false;
+    }
+    return has_sample;
+  }
+
   AppHelper app_helper_;
   TemporaryFile perf_data_file_;
 };
@@ -790,6 +864,7 @@
   }
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, app_option_for_debuggable_app) {
   OMIT_TEST_ON_NON_NATIVE_ABIS();
   TEST_REQUIRE_APPS();
@@ -799,6 +874,7 @@
   TestRecordingApps("com.android.simpleperf.debuggable", "debuggable");
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, app_option_for_profileable_app) {
   OMIT_TEST_ON_NON_NATIVE_ABIS();
   TEST_REQUIRE_APPS();
@@ -828,6 +904,7 @@
 }
 #endif  // defined(__ANDROID__)
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, record_java_app) {
 #if defined(__ANDROID__)
   OMIT_TEST_ON_NON_NATIVE_ABIS();
@@ -858,6 +935,7 @@
 #endif
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, record_native_app) {
 #if defined(__ANDROID__)
   // In case of non-native ABI guest symbols are never directly executed, thus
@@ -893,6 +971,7 @@
 #endif
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, check_trampoline_after_art_jni_methods) {
   // Test if art jni methods are called by art_jni_trampoline.
 #if defined(__ANDROID__)
@@ -959,10 +1038,12 @@
 #endif
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, no_cut_samples_option) {
   ASSERT_TRUE(RunRecordCmd({"--no-cut-samples"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, cs_etm_event) {
   if (!ETMRecorder::GetInstance().CheckEtmSupport().ok()) {
     GTEST_LOG_(INFO) << "Omit this test since etm isn't supported on this device";
@@ -997,6 +1078,7 @@
   ASSERT_TRUE(has_aux);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, cs_etm_system_wide) {
   TEST_REQUIRE_ROOT();
   if (!ETMRecorder::GetInstance().CheckEtmSupport().ok()) {
@@ -1006,6 +1088,7 @@
   ASSERT_TRUE(RunRecordCmd({"-e", "cs-etm", "-a"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, aux_buffer_size_option) {
   if (!ETMRecorder::GetInstance().CheckEtmSupport().ok()) {
     GTEST_LOG_(INFO) << "Omit this test since etm isn't supported on this device";
@@ -1018,6 +1101,7 @@
   ASSERT_FALSE(RunRecordCmd({"-e", "cs-etm", "--aux-buffer-size", "12k"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, addr_filter_option) {
   TEST_REQUIRE_HW_COUNTER();
   if (!ETMRecorder::GetInstance().CheckEtmSupport().ok()) {
@@ -1078,6 +1162,7 @@
   ASSERT_TRUE(RunRecordCmd({"-e", "cs-etm", "--addr-filter", filter}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, decode_etm_option) {
   if (!ETMRecorder::GetInstance().CheckEtmSupport().ok()) {
     GTEST_LOG_(INFO) << "Omit this test since etm isn't supported on this device";
@@ -1087,6 +1172,7 @@
   ASSERT_TRUE(RunRecordCmd({"-e", "cs-etm", "--decode-etm", "--exclude-perf"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, record_timestamp) {
   if (!ETMRecorder::GetInstance().CheckEtmSupport().ok()) {
     GTEST_LOG_(INFO) << "Omit this test since etm isn't supported on this device";
@@ -1095,6 +1181,7 @@
   ASSERT_TRUE(RunRecordCmd({"-e", "cs-etm", "--record-timestamp"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, record_cycles) {
   if (!ETMRecorder::GetInstance().CheckEtmSupport().ok()) {
     GTEST_LOG_(INFO) << "Omit this test since etm isn't supported on this device";
@@ -1103,6 +1190,7 @@
   ASSERT_TRUE(RunRecordCmd({"-e", "cs-etm", "--record-cycles"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, cycle_threshold) {
   if (!ETMRecorder::GetInstance().CheckEtmSupport().ok()) {
     GTEST_LOG_(INFO) << "Omit this test since etm isn't supported on this device";
@@ -1112,6 +1200,7 @@
                             "--cycle-threshold", "8"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, binary_option) {
   if (!ETMRecorder::GetInstance().CheckEtmSupport().ok()) {
     GTEST_LOG_(INFO) << "Omit this test since etm isn't supported on this device";
@@ -1120,6 +1209,7 @@
   ASSERT_TRUE(RunRecordCmd({"-e", "cs-etm", "--decode-etm", "--binary", ".*"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, pmu_event_option) {
   TEST_REQUIRE_PMU_COUNTER();
   TEST_REQUIRE_HW_COUNTER();
@@ -1135,6 +1225,7 @@
   TEST_IN_ROOT(ASSERT_TRUE(RunRecordCmd({"-e", event_string})));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, exclude_perf_option) {
   ASSERT_TRUE(RunRecordCmd({"--exclude-perf"}));
   if (IsRoot()) {
@@ -1155,6 +1246,7 @@
   }
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, tp_filter_option) {
   TEST_REQUIRE_HOST_ROOT();
   TEST_REQUIRE_TRACEPOINT_EVENTS();
@@ -1175,6 +1267,7 @@
   }
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, ParseAddrFilterOption) {
   auto option_to_str = [](const std::string& option) {
     auto filters = ParseAddrFilterOption(option);
@@ -1207,6 +1300,7 @@
   ASSERT_EQ(option_to_str("start 0x12345678,stop 0x1234567a"), "start 0x12345678,stop 0x1234567a");
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, kprobe_option) {
   TEST_REQUIRE_ROOT();
   EventSelectionSet event_selection_set(false);
@@ -1221,6 +1315,7 @@
   ASSERT_TRUE(RunRecordCmd({"--group", "kprobes:do_sys_openat2"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, record_filter_options) {
   ASSERT_TRUE(
       RunRecordCmd({"--exclude-pid", "1,2", "--exclude-tid", "3,4", "--exclude-process-name",
@@ -1230,6 +1325,7 @@
                     "processB", "--include-thread-name", "threadB", "--include-uid", "5,6"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, keep_failed_unwinding_result_option) {
   OMIT_TEST_ON_NON_NATIVE_ABIS();
   std::vector<std::unique_ptr<Workload>> workloads;
@@ -1239,6 +1335,7 @@
       {"-p", pid, "-g", "--keep-failed-unwinding-result", "--keep-failed-unwinding-debug-info"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, kernel_address_warning) {
   TEST_REQUIRE_NON_ROOT();
   const std::string warning_msg = "Access to kernel symbol addresses is restricted.";
@@ -1263,6 +1360,7 @@
   ASSERT_EQ(output.find(warning_msg, pos + warning_msg.size()), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, add_meta_info_option) {
   TemporaryFile tmpfile;
   ASSERT_TRUE(RunRecordCmd({"--add-meta-info", "key1=value1", "--add-meta-info", "key2=value2"},
@@ -1284,6 +1382,7 @@
   ASSERT_FALSE(RunRecordCmd({"--add-meta-info", "=value1"}, tmpfile.path));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, device_meta_info) {
 #if defined(__ANDROID__)
   TemporaryFile tmpfile;
@@ -1303,6 +1402,7 @@
 #endif
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, add_counter_option) {
   TEST_REQUIRE_HW_COUNTER();
   TemporaryFile tmpfile;
@@ -1324,10 +1424,12 @@
   ASSERT_TRUE(has_sample);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, user_buffer_size_option) {
   ASSERT_TRUE(RunRecordCmd({"--user-buffer-size", "256M"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, record_process_name) {
   TemporaryFile tmpfile;
   ASSERT_TRUE(RecordCmd()->Run({"-e", GetDefaultEvent(), "-o", tmpfile.path, "sleep", SLEEP_SEC}));
@@ -1346,6 +1448,7 @@
   ASSERT_TRUE(has_comm);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(record_cmd, delay_option) {
   TemporaryFile tmpfile;
   ASSERT_TRUE(RecordCmd()->Run(
diff --git a/simpleperf/cmd_report.cpp b/simpleperf/cmd_report.cpp
index 524174e..f2fb527 100644
--- a/simpleperf/cmd_report.cpp
+++ b/simpleperf/cmd_report.cpp
@@ -449,6 +449,7 @@
 "                      The default sort keys are:\n"
 "                        comm,pid,tid,dso,symbol\n"
 "--symfs <dir>         Look for files with symbols relative to this directory.\n"
+"--symdir <dir>        Look for files with symbols in a directory recursively.\n"
 "--vmlinux <file>      Parse kernel symbols from <file>.\n"
 "\n"
 "Sample filter options:\n"
@@ -585,6 +586,7 @@
       {"--sort", {OptionValueType::STRING, OptionType::SINGLE}},
       {"--symbols", {OptionValueType::STRING, OptionType::MULTIPLE}},
       {"--symfs", {OptionValueType::STRING, OptionType::SINGLE}},
+      {"--symdir", {OptionValueType::STRING, OptionType::SINGLE}},
       {"--vmlinux", {OptionValueType::STRING, OptionType::SINGLE}},
   };
   OptionFormatMap record_filter_options = GetRecordFilterOptionFormats(false);
@@ -692,6 +694,11 @@
       return false;
     }
   }
+  if (auto value = options.PullValue("--symdir"); value) {
+    if (!Dso::AddSymbolDir(*value->str_value)) {
+      return false;
+    }
+  }
   if (auto value = options.PullValue("--vmlinux"); value) {
     Dso::SetVmlinux(*value->str_value);
   }
diff --git a/simpleperf/cmd_report_sample_test.cpp b/simpleperf/cmd_report_sample_test.cpp
index d71dce2..b544f7b 100644
--- a/simpleperf/cmd_report_sample_test.cpp
+++ b/simpleperf/cmd_report_sample_test.cpp
@@ -29,16 +29,19 @@
   return CreateCommandInstance("report-sample");
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_report_sample, text) {
   ASSERT_TRUE(ReportSampleCmd()->Run({"-i", GetTestData(PERF_DATA_WITH_SYMBOLS)}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_report_sample, output_option) {
   TemporaryFile tmpfile;
   ASSERT_TRUE(
       ReportSampleCmd()->Run({"-i", GetTestData(PERF_DATA_WITH_SYMBOLS), "-o", tmpfile.path}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_report_sample, show_callchain_option) {
   TemporaryFile tmpfile;
   ASSERT_TRUE(ReportSampleCmd()->Run(
@@ -58,6 +61,7 @@
   ASSERT_TRUE(android::base::ReadFileToString(tmpfile2.path, protobuf_report));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_report_sample, protobuf_option) {
   std::string data;
   GetProtobufReport(PERF_DATA_WITH_SYMBOLS, &data);
@@ -66,6 +70,7 @@
   ASSERT_NE(data.find("file:"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_report_sample, no_skipped_file_id) {
   std::string data;
   GetProtobufReport(PERF_DATA_WITH_WRONG_IP_IN_CALLCHAIN, &data);
@@ -73,12 +78,14 @@
   ASSERT_EQ(data.find("unknown"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_report_sample, sample_has_event_count) {
   std::string data;
   GetProtobufReport(PERF_DATA_WITH_SYMBOLS, &data);
   ASSERT_NE(data.find("event_count:"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_report_sample, has_thread_record) {
   std::string data;
   GetProtobufReport(PERF_DATA_WITH_SYMBOLS, &data);
@@ -86,6 +93,7 @@
   ASSERT_NE(data.find("thread_name: t2"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_report_sample, trace_offcpu) {
   std::string data;
   GetProtobufReport("perf_with_trace_offcpu_v2.data", &data);
@@ -101,6 +109,7 @@
   }
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_report_sample, have_clear_callchain_end_in_protobuf_output) {
   std::string data;
   GetProtobufReport("perf_with_trace_offcpu_v2.data", &data, {"--show-callchain"});
@@ -108,6 +117,7 @@
   ASSERT_EQ(data.find("_start_main"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_report_sample, app_device_info_in_meta_info) {
   std::string data;
   GetProtobufReport("perf_with_meta_info.data", &data);
@@ -117,6 +127,7 @@
   ASSERT_NE(data.find("android_build_type: userdebug"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_report_sample, remove_unknown_kernel_symbols) {
   std::string data;
   // Test --remove-unknown-kernel-symbols on perf.data with kernel_symbols_available=false.
@@ -148,6 +159,7 @@
   ASSERT_NE(data.find("path: /system/lib64/libc.so"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_report_sample, show_art_frames_option) {
   std::string data;
   GetProtobufReport(PERF_DATA_WITH_INTERPRETER_FRAMES, &data, {"--show-callchain"});
@@ -157,6 +169,7 @@
   ASSERT_NE(data.find("artMterpAsmInstructionStart"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_report_sample, show_execution_type_option) {
   std::string data;
   GetProtobufReport("perf_display_bitmaps.data", &data,
@@ -174,6 +187,7 @@
   ASSERT_NE(data.find("execution_type: art_method"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_report_sample, show_symbols_before_and_after_demangle) {
   std::string data;
   GetProtobufReport(PERF_DATA_WITH_INTERPRETER_FRAMES, &data, {"--show-callchain"});
@@ -183,6 +197,7 @@
             std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_report_sample, symdir_option) {
   std::string data;
   GetProtobufReport(PERF_DATA_FOR_BUILD_ID_CHECK, &data);
@@ -192,6 +207,7 @@
   ASSERT_NE(data.find("symbol: main"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_report_sample, show_art_jni_methods) {
   std::string data;
   GetProtobufReport("perf_display_bitmaps.data", &data, {"--show-callchain"});
@@ -200,6 +216,7 @@
   ASSERT_EQ(data.find("art_jni_trampoline"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_report_sample, show_unwinding_result) {
   std::string data;
   GetProtobufReport("perf_with_failed_unwinding_debug_info.data", &data,
@@ -207,6 +224,7 @@
   ASSERT_NE(data.find("error_code: ERROR_INVALID_MAP"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_report_sample, proguard_mapping_file_option) {
   std::string data;
   // Symbols aren't de-obfuscated without proguard mapping file.
@@ -226,6 +244,7 @@
             std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_report_sample, exclude_include_pid_options) {
   std::string data;
   GetProtobufReport("perf_display_bitmaps.data", &data, {"--exclude-pid", "31850"});
@@ -235,6 +254,7 @@
   ASSERT_NE(data.find("thread_id: 31850"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_report_sample, exclude_include_tid_options) {
   std::string data;
   GetProtobufReport("perf_display_bitmaps.data", &data, {"--exclude-tid", "31881"});
@@ -244,6 +264,7 @@
   ASSERT_NE(data.find("thread_id: 31881"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_report_sample, exclude_include_process_name_options) {
   std::string data;
   GetProtobufReport("perf_display_bitmaps.data", &data,
@@ -255,6 +276,7 @@
   ASSERT_NE(data.find("thread_id: 31881"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_report_sample, exclude_include_thread_name_options) {
   std::string data;
   GetProtobufReport("perf_display_bitmaps.data", &data,
@@ -266,6 +288,7 @@
   ASSERT_NE(data.find("thread_id: 31850"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_report_sample, filter_file_option) {
   std::string filter_data =
       "GLOBAL_BEGIN 684943449406175\n"
@@ -278,6 +301,7 @@
   ASSERT_EQ(data.find("thread_id: 31850"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(cmd_report_sample, remove_gaps_option) {
   auto get_sample_count = [](const std::string& s) {
     size_t count = 0;
diff --git a/simpleperf/cmd_report_test.cpp b/simpleperf/cmd_report_test.cpp
index 6dfbae5..9170beb 100644
--- a/simpleperf/cmd_report_test.cpp
+++ b/simpleperf/cmd_report_test.cpp
@@ -37,19 +37,27 @@
   return CreateCommandInstance("report");
 }
 
+// @CddTest = 6.1/C-0-2
 class ReportCommandTest : public ::testing::Test {
  protected:
   void Report(const std::string& perf_data,
-              const std::vector<std::string>& add_args = std::vector<std::string>()) {
-    ReportRaw(GetTestData(perf_data), add_args);
+              const std::vector<std::string>& add_args = std::vector<std::string>(),
+              bool with_symfs = true) {
+    ReportRaw(GetTestData(perf_data), add_args, with_symfs);
   }
 
   void ReportRaw(const std::string& perf_data,
-                 const std::vector<std::string>& add_args = std::vector<std::string>()) {
+                 const std::vector<std::string>& add_args = std::vector<std::string>(),
+                 bool with_symfs = true) {
     success = false;
     TemporaryFile tmp_file;
-    std::vector<std::string> args = {"-i", perf_data,    "--symfs", GetTestDataDir(),
-                                     "-o", tmp_file.path};
+    std::vector<std::string> args = {"-i", perf_data, "-o", tmp_file.path};
+
+    if (with_symfs) {
+      args.emplace_back("--symfs");
+      args.emplace_back(GetTestDataDir());
+    }
+
     args.insert(args.end(), add_args.begin(), add_args.end());
     ASSERT_TRUE(ReportCmd()->Run(args));
     ASSERT_TRUE(android::base::ReadFileToString(tmp_file.path, &content));
@@ -83,18 +91,21 @@
   bool success;
 };
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, no_option) {
   Report(PERF_DATA);
   ASSERT_TRUE(success);
   ASSERT_NE(content.find("GlobalFunc"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, report_symbol_from_elf_file_with_mini_debug_info) {
   Report(PERF_DATA_WITH_MINI_DEBUG_INFO);
   ASSERT_TRUE(success);
   ASSERT_NE(content.find("GlobalFunc"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, sort_option_pid) {
   Report(PERF_DATA, {"--sort", "pid"});
   ASSERT_TRUE(success);
@@ -105,6 +116,7 @@
   ASSERT_LT(line_index + 2, lines.size());
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, sort_option_more_than_one) {
   Report(PERF_DATA, {"--sort", "comm,pid,dso,symbol"});
   ASSERT_TRUE(success);
@@ -120,6 +132,7 @@
   ASSERT_EQ(lines[line_index].find("Tid"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, children_option) {
   Report(CALLGRAPH_FP_PERF_DATA, {"--children", "--sort", "symbol"});
   ASSERT_TRUE(success);
@@ -164,6 +177,7 @@
   return found;
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, callgraph_option) {
   Report(CALLGRAPH_FP_PERF_DATA, {"-g"});
   ASSERT_TRUE(success);
@@ -201,6 +215,7 @@
   return true;
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, pid_filter_option) {
   Report(PERF_DATA_WITH_MULTIPLE_PIDS_AND_TIDS, {"--sort", "pid"});
   ASSERT_TRUE(success);
@@ -221,6 +236,7 @@
   ASSERT_NE(content.find("17445"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, wrong_pid_filter_option) {
   ASSERT_EXIT(
       {
@@ -230,6 +246,7 @@
       testing::ExitedWithCode(1), "invalid pid: bogus");
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, tid_filter_option) {
   Report(PERF_DATA_WITH_MULTIPLE_PIDS_AND_TIDS, {"--sort", "tid"});
   ASSERT_TRUE(success);
@@ -243,6 +260,7 @@
   ASSERT_TRUE(AllItemsWithString(lines, {"17441", "17445"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, wrong_tid_filter_option) {
   ASSERT_EXIT(
       {
@@ -252,6 +270,7 @@
       testing::ExitedWithCode(1), "Invalid tid 'bogus'");
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, comm_filter_option) {
   Report(PERF_DATA, {"--sort", "comm"});
   ASSERT_TRUE(success);
@@ -265,6 +284,7 @@
   ASSERT_TRUE(AllItemsWithString(lines, {"t1", "t2"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, dso_filter_option) {
   Report(PERF_DATA, {"--sort", "dso"});
   ASSERT_TRUE(success);
@@ -278,6 +298,7 @@
   ASSERT_TRUE(AllItemsWithString(lines, {"/t1", "/t2"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, symbol_filter_option) {
   Report(PERF_DATA_WITH_SYMBOLS, {"--sort", "symbol"});
   ASSERT_TRUE(success);
@@ -291,6 +312,7 @@
   ASSERT_TRUE(AllItemsWithString(lines, {"main", "func2(int, int)"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, dso_symbol_filter_with_children_option) {
   // dso and symbol filter should filter different layers of the callchain separately.
   Report("perf_display_bitmaps.data", {"--dsos", "/apex/com.android.runtime/lib64/libart.so",
@@ -305,6 +327,7 @@
   ASSERT_NE(content.find("51500000  2500000  MterpInvokeVirtual"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, use_branch_address) {
   Report(BRANCH_PERF_DATA, {"-b", "--sort", "symbol_from,symbol_to"});
   std::set<std::pair<std::string, std::string>> hit_set;
@@ -326,6 +349,7 @@
             hit_set.end());
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, report_symbols_of_nativelib_in_apk) {
   Report(NATIVELIB_IN_APK_PERF_DATA);
   ASSERT_TRUE(success);
@@ -333,6 +357,7 @@
   ASSERT_NE(content.find("Func2"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, report_more_than_one_event_types) {
   Report(PERF_DATA_WITH_TWO_EVENT_TYPES);
   ASSERT_TRUE(success);
@@ -343,12 +368,14 @@
   ASSERT_NE(pos = content.find("Samples:", pos), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, report_kernel_symbol) {
   Report(PERF_DATA_WITH_KERNEL_SYMBOL);
   ASSERT_TRUE(success);
   ASSERT_NE(content.find("perf_event_aux"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, report_dumped_symbols) {
   Report(PERF_DATA_WITH_SYMBOLS);
   ASSERT_TRUE(success);
@@ -358,6 +385,7 @@
   ASSERT_NE(content.find("memcpy"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, report_dumped_symbols_with_symfs_dir) {
   // Check if we can report symbols when they appear both in perf.data and symfs dir.
   Report(PERF_DATA_WITH_SYMBOLS, {"--symfs", GetTestDataDir()});
@@ -365,17 +393,28 @@
   ASSERT_NE(content.find("main"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
+TEST_F(ReportCommandTest, report_dumped_symbols_with_symdir) {
+  // Check if we can report symbols by specifying symdir.
+  Report(PERF_DATA, {"--symdir", GetTestDataDir()}, false);
+  ASSERT_TRUE(success);
+  ASSERT_NE(content.find("GlobalFunc"), std::string::npos);
+}
+
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, report_without_symfs_dir) {
   TemporaryFile tmpfile;
   ASSERT_TRUE(ReportCmd()->Run({"-i", GetTestData(PERF_DATA), "-o", tmpfile.path}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, report_sort_vaddr_in_file) {
   Report(PERF_DATA, {"--sort", "vaddr_in_file"});
   ASSERT_TRUE(success);
   ASSERT_NE(content.find("VaddrInFile"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, check_build_id) {
   Report(PERF_DATA_FOR_BUILD_ID_CHECK, {"--symfs", GetTestData(CORRECT_SYMFS_FOR_BUILD_ID_CHECK)});
   ASSERT_TRUE(success);
@@ -395,6 +434,7 @@
       testing::ExitedWithCode(0), "failed to read symbols from /elf_for_build_id_check");
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, no_show_ip_option) {
   Report(PERF_DATA);
   ASSERT_TRUE(success);
@@ -404,6 +444,7 @@
   ASSERT_NE(content.find("unknown"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, read_elf_file_warning) {
   ASSERT_EXIT(
       {
@@ -419,11 +460,13 @@
       testing::ExitedWithCode(0), "failed to read symbols from /elf: File not found");
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, report_data_generated_by_linux_perf) {
   Report(PERF_DATA_GENERATED_BY_LINUX_PERF);
   ASSERT_TRUE(success);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, max_stack_and_percent_limit_option) {
   Report(PERF_DATA_MAX_STACK_AND_PERCENT_LIMIT, {"-g"});
   ASSERT_TRUE(success);
@@ -444,6 +487,7 @@
   ASSERT_NE(content.find("89.03"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, percent_limit_option) {
   Report(PERF_DATA);
   ASSERT_TRUE(success);
@@ -455,16 +499,19 @@
   ASSERT_EQ(content.find("3.23%"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, kallsyms_option) {
   Report(PERF_DATA, {"--kallsyms", GetTestData("kallsyms")});
   ASSERT_TRUE(success);
   ASSERT_NE(content.find("FakeKernelSymbol"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, invalid_perf_data) {
   ASSERT_FALSE(ReportCmd()->Run({"-i", GetTestData(INVALID_PERF_DATA)}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, raw_period_option) {
   Report(PERF_DATA, {"--raw-period"});
   ASSERT_TRUE(success);
@@ -472,6 +519,7 @@
   ASSERT_EQ(content.find('%'), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, full_callgraph_option) {
   Report(CALLGRAPH_FP_PERF_DATA, {"-g"});
   ASSERT_TRUE(success);
@@ -481,6 +529,7 @@
   ASSERT_EQ(content.find("skipped in brief callgraph mode"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, report_offcpu_time) {
   Report(PERF_DATA_WITH_TRACE_OFFCPU, {"--children"});
   ASSERT_TRUE(success);
@@ -496,11 +545,13 @@
   ASSERT_TRUE(found);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, report_big_trace_data) {
   Report(PERF_DATA_WITH_BIG_TRACE_DATA);
   ASSERT_TRUE(success);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, csv_option) {
   Report(PERF_DATA, {"--csv"});
   ASSERT_TRUE(success);
@@ -511,6 +562,7 @@
   ASSERT_NE(content.find("AccEventCount,SelfEventCount,EventName"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, csv_separator_option) {
   Report(PERF_DATA, {"--csv", "--csv-separator", ";"});
   ASSERT_TRUE(success);
@@ -518,6 +570,7 @@
   ASSERT_NE(content.find(";cpu-cycles"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, dso_path_for_jit_cache) {
   Report("perf_with_jit_symbol.data", {"--sort", "dso"});
   ASSERT_TRUE(success);
@@ -529,12 +582,14 @@
   ASSERT_NE(content.find("[JIT app cache]"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, generic_jit_symbols) {
   Report("perf_with_generic_git_symbols.data", {"--sort", "symbol"});
   ASSERT_TRUE(success);
   ASSERT_NE(std::string::npos, content.find("generic_jit_symbol_one"));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, cpu_option) {
   Report("perf.data");
   ASSERT_TRUE(success);
@@ -551,6 +606,7 @@
   ASSERT_FALSE(ReportCmd()->Run({"-i", GetTestData("perf.data"), "--cpu", "-2"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, print_event_count_option) {
   // Report record file not recorded with --add-counter.
   Report("perf.data", {"--print-event-count"});
@@ -583,6 +639,7 @@
           ->Search(content));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, exclude_include_pid_options) {
   Report(PERF_DATA_WITH_MULTIPLE_PIDS_AND_TIDS, {"--sort", "pid", "--exclude-pid", "17441"});
   ASSERT_TRUE(success);
@@ -592,6 +649,7 @@
   ASSERT_TRUE(AllItemsWithString(lines, {"17441"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, exclude_include_tid_options) {
   Report(PERF_DATA_WITH_MULTIPLE_PIDS_AND_TIDS,
          {"--sort", "tid", "--exclude-tid", "17441,17443,17444"});
@@ -603,6 +661,7 @@
   ASSERT_TRUE(AllItemsWithString(lines, {"17441", "17443", "17444"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, exclude_include_process_name_options) {
   Report(PERF_DATA_WITH_MULTIPLE_PIDS_AND_TIDS, {"--sort", "comm", "--exclude-process-name", "t1"});
   ASSERT_TRUE(success);
@@ -612,6 +671,7 @@
   ASSERT_TRUE(AllItemsWithString(lines, {"t1"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, exclude_include_thread_name_options) {
   Report(PERF_DATA_WITH_MULTIPLE_PIDS_AND_TIDS, {"--sort", "comm", "--exclude-thread-name", "t1"});
   ASSERT_TRUE(success);
@@ -621,6 +681,7 @@
   ASSERT_TRUE(AllItemsWithString(lines, {"t1"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, filter_file_option) {
   std::string filter_data =
       "GLOBAL_BEGIN 684943449406175\n"
@@ -645,6 +706,7 @@
   return CreateCommandInstance("record");
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, dwarf_callgraph) {
   TEST_REQUIRE_HW_COUNTER();
   OMIT_TEST_ON_NON_NATIVE_ABIS();
@@ -658,6 +720,7 @@
   ASSERT_TRUE(success);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, report_dwarf_callgraph_of_nativelib_in_apk) {
   Report(NATIVELIB_IN_APK_PERF_DATA, {"-g"});
   ASSERT_NE(content.find(GetUrlInApk(APK_FILE, NATIVELIB_IN_APK)), std::string::npos);
@@ -666,6 +729,7 @@
   ASSERT_NE(content.find("GlobalFunc"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ReportCommandTest, exclude_kernel_callchain) {
   TEST_REQUIRE_HW_COUNTER();
   TEST_REQUIRE_HOST_ROOT();
diff --git a/simpleperf/cmd_stat_test.cpp b/simpleperf/cmd_stat_test.cpp
index 86c7ae8..c47ad72 100644
--- a/simpleperf/cmd_stat_test.cpp
+++ b/simpleperf/cmd_stat_test.cpp
@@ -36,26 +36,32 @@
   return CreateCommandInstance("stat");
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, no_options) {
   ASSERT_TRUE(StatCmd()->Run({"sleep", "1"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, event_option) {
   ASSERT_TRUE(StatCmd()->Run({"-e", "cpu-clock,task-clock", "sleep", "1"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, system_wide_option) {
   TEST_IN_ROOT(ASSERT_TRUE(StatCmd()->Run({"-a", "sleep", "1"})));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, verbose_option) {
   ASSERT_TRUE(StatCmd()->Run({"--verbose", "sleep", "1"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, tracepoint_event) {
   TEST_IN_ROOT(ASSERT_TRUE(StatCmd()->Run({"-a", "-e", "sched:sched_switch", "sleep", "1"})));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, rN_event) {
   TEST_REQUIRE_HW_COUNTER();
   OMIT_TEST_ON_NON_NATIVE_ABIS();
@@ -79,6 +85,7 @@
   ASSERT_TRUE(StatCmd()->Run({"-e", event_name, "sleep", "1"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, pmu_event) {
   TEST_REQUIRE_PMU_COUNTER();
   TEST_REQUIRE_HW_COUNTER();
@@ -96,6 +103,7 @@
   TEST_IN_ROOT(ASSERT_TRUE(StatCmd()->Run({"-a", "-e", event_string, "sleep", "1"})));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, event_modifier) {
   TEST_REQUIRE_HW_COUNTER();
   ASSERT_TRUE(StatCmd()->Run({"-e", "cpu-cycles:u,cpu-cycles:k", "sleep", "1"}));
@@ -121,6 +129,7 @@
   }
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, existing_processes) {
   std::vector<std::unique_ptr<Workload>> workloads;
   CreateProcesses(2, &workloads);
@@ -129,6 +138,7 @@
   ASSERT_TRUE(StatCmd()->Run({"-p", pid_list, "sleep", "1"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, existing_threads) {
   std::vector<std::unique_ptr<Workload>> workloads;
   CreateProcesses(2, &workloads);
@@ -138,11 +148,13 @@
   ASSERT_TRUE(StatCmd()->Run({"-t", tid_list, "sleep", "1"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, no_monitored_threads) {
   ASSERT_FALSE(StatCmd()->Run({}));
   ASSERT_FALSE(StatCmd()->Run({""}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, group_option) {
   TEST_REQUIRE_HW_COUNTER();
   ASSERT_TRUE(StatCmd()->Run({"--group", "cpu-clock,page-faults", "sleep", "1"}));
@@ -151,6 +163,7 @@
                               "cpu-cycles:k,instructions:k", "sleep", "1"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, auto_generated_summary) {
   TEST_REQUIRE_HW_COUNTER();
   TemporaryFile tmp_file;
@@ -167,11 +180,13 @@
   ASSERT_NE(s.npos, s.find("instructions", pos));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, duration_option) {
   ASSERT_TRUE(StatCmd()->Run({"--duration", "1.2", "-p", std::to_string(getpid()), "--in-app"}));
   ASSERT_TRUE(StatCmd()->Run({"--duration", "1", "sleep", "2"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, interval_option) {
   TemporaryFile tmp_file;
   ASSERT_TRUE(StatCmd()->Run(
@@ -188,16 +203,19 @@
   ASSERT_EQ(count, 2UL);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, interval_option_in_system_wide) {
   TEST_IN_ROOT(ASSERT_TRUE(StatCmd()->Run({"-a", "--interval", "100", "--duration", "0.3"})));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, interval_only_values_option) {
   ASSERT_TRUE(StatCmd()->Run({"--interval", "500", "--interval-only-values", "sleep", "2"}));
   TEST_IN_ROOT(ASSERT_TRUE(
       StatCmd()->Run({"-a", "--interval", "100", "--interval-only-values", "--duration", "0.3"})));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, no_modifier_for_clock_events) {
   for (const std::string& e : {"cpu-clock", "task-clock"}) {
     for (const std::string& m : {"u", "k"}) {
@@ -207,6 +225,7 @@
   }
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, handle_SIGHUP) {
   std::thread thread([]() {
     sleep(1);
@@ -216,6 +235,7 @@
   ASSERT_TRUE(StatCmd()->Run({"sleep", "1000000"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, stop_when_no_more_targets) {
   std::atomic<int> tid(0);
   std::thread thread([&]() {
@@ -228,6 +248,7 @@
   ASSERT_TRUE(StatCmd()->Run({"-t", std::to_string(tid), "--in-app"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, sample_rate_should_be_zero) {
   TEST_REQUIRE_HW_COUNTER();
   EventSelectionSet set(true);
@@ -244,6 +265,7 @@
   }
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, calculating_cpu_frequency) {
   TEST_REQUIRE_HW_COUNTER();
   CaptureStdout capture;
@@ -269,6 +291,7 @@
   ASSERT_NEAR(cpu_frequency, calculated_frequency, 1e-3);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, set_comm_in_another_thread) {
   // Test a kernel bug which was fixed in 3.15. If kernel panic happens, please cherry pick kernel
   // patch: e041e328c4b41e perf: Fix perf_event_comm() vs. exec() assumption
@@ -321,6 +344,7 @@
   ASSERT_TRUE(StatCmd()->Run({"--app", app_name, "--duration", "3"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, app_option_for_debuggable_app) {
   TEST_REQUIRE_APPS();
   SetRunInAppToolForTesting(true, false);
@@ -329,12 +353,14 @@
   TestStatingApps("com.android.simpleperf.debuggable");
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, app_option_for_profileable_app) {
   TEST_REQUIRE_APPS();
   SetRunInAppToolForTesting(false, true);
   TestStatingApps("com.android.simpleperf.profileable");
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, use_devfreq_counters_option) {
 #if defined(__ANDROID__)
   TEST_IN_ROOT(StatCmd()->Run({"--use-devfreq-counters", "sleep", "0.1"}));
@@ -343,21 +369,25 @@
 #endif
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, per_thread_option) {
   ASSERT_TRUE(StatCmd()->Run({"--per-thread", "sleep", "0.1"}));
   TEST_IN_ROOT(StatCmd()->Run({"--per-thread", "-a", "--duration", "0.1"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, per_core_option) {
   ASSERT_TRUE(StatCmd()->Run({"--per-core", "sleep", "0.1"}));
   TEST_IN_ROOT(StatCmd()->Run({"--per-core", "-a", "--duration", "0.1"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, sort_option) {
   ASSERT_TRUE(
       StatCmd()->Run({"--per-thread", "--per-core", "--sort", "cpu,count", "sleep", "0.1"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, counter_sum) {
   PerfCounter counter;
   counter.value = 1;
@@ -382,10 +412,12 @@
   ASSERT_EQ(counter.time_running, 6);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, print_hw_counter_option) {
   ASSERT_TRUE(StatCmd()->Run({"--print-hw-counter"}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, record_different_counters_for_different_cpus) {
   std::vector<int> online_cpus = GetOnlineCpus();
   ASSERT_FALSE(online_cpus.empty());
@@ -412,6 +444,7 @@
   ASSERT_TRUE(has_task_clock) << output;
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, kprobe_option) {
   TEST_REQUIRE_ROOT();
   EventSelectionSet event_selection_set(false);
@@ -427,6 +460,7 @@
   ASSERT_TRUE(StatCmd()->Run({"--group", "kprobes:do_sys_openat2", "-a", "--duration", SLEEP_SEC}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(stat_cmd, tp_filter_option) {
   TEST_REQUIRE_HOST_ROOT();
   TEST_REQUIRE_TRACEPOINT_EVENTS();
@@ -434,6 +468,7 @@
       {"-e", "sched:sched_switch", "--tp-filter", "prev_comm != sleep", "sleep", SLEEP_SEC}));
 }
 
+// @CddTest = 6.1/C-0-2
 class StatCmdSummaryBuilderTest : public ::testing::Test {
  protected:
   struct CounterArg {
@@ -485,6 +520,7 @@
   std::vector<std::string> sort_keys_;
 };
 
+// @CddTest = 6.1/C-0-2
 TEST_F(StatCmdSummaryBuilderTest, multiple_events) {
   AddCounter({.event_id = 0, .value = 1, .time_enabled = 1, .time_running = 1});
   AddCounter({.event_id = 1, .value = 2, .time_enabled = 2, .time_running = 2});
@@ -498,6 +534,7 @@
   ASSERT_NEAR(summaries[1].scale, 1.0, 1e-5);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(StatCmdSummaryBuilderTest, default_aggregate) {
   AddCounter({.tid = 0, .cpu = 0, .value = 1, .time_enabled = 1, .time_running = 1});
   AddCounter({.tid = 0, .cpu = 1, .value = 1, .time_enabled = 1, .time_running = 1});
@@ -509,6 +546,7 @@
   ASSERT_NEAR(summaries[0].scale, 1.25, 1e-5);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(StatCmdSummaryBuilderTest, per_thread_aggregate) {
   AddCounter({.tid = 0, .cpu = 0, .value = 1, .time_enabled = 1, .time_running = 1});
   AddCounter({.tid = 0, .cpu = 1, .value = 1, .time_enabled = 1, .time_running = 1});
@@ -526,6 +564,7 @@
   ASSERT_NEAR(summaries[1].scale, 1.0, 1e-5);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(StatCmdSummaryBuilderTest, per_core_aggregate) {
   AddCounter({.tid = 0, .cpu = 0, .value = 1, .time_enabled = 1, .time_running = 1});
   AddCounter({.tid = 0, .cpu = 1, .value = 1, .time_enabled = 1, .time_running = 1});
@@ -543,6 +582,7 @@
   ASSERT_NEAR(summaries[1].scale, 1.5, 1e-5);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(StatCmdSummaryBuilderTest, per_thread_core_aggregate) {
   AddCounter({.tid = 0, .cpu = 0, .value = 1, .time_enabled = 1, .time_running = 1});
   AddCounter({.tid = 0, .cpu = 1, .value = 2, .time_enabled = 1, .time_running = 1});
@@ -568,6 +608,7 @@
   ASSERT_NEAR(summaries[3].scale, 1.0, 1e-5);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(StatCmdSummaryBuilderTest, sort_key_count) {
   sort_keys_ = {"count"};
   AddCounter({.tid = 0, .cpu = 0, .value = 1});
@@ -577,6 +618,7 @@
   ASSERT_EQ(summaries[1].count, 1);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(StatCmdSummaryBuilderTest, sort_key_count_per_thread) {
   sort_keys_ = {"count_per_thread", "count"};
   AddCounter({.tid = 0, .cpu = 0, .value = 1});
@@ -588,6 +630,7 @@
   ASSERT_EQ(summaries[2].count, 3);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(StatCmdSummaryBuilderTest, sort_key_cpu) {
   sort_keys_ = {"cpu"};
   AddCounter({.tid = 0, .cpu = 1, .value = 2});
@@ -597,6 +640,7 @@
   ASSERT_EQ(summaries[1].cpu, 1);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(StatCmdSummaryBuilderTest, sort_key_pid_tid_name) {
   AddCounter({.tid = 0, .cpu = 0, .value = 1});
   AddCounter({.tid = 1, .cpu = 0, .value = 2});
@@ -609,6 +653,7 @@
   }
 }
 
+// @CddTest = 6.1/C-0-2
 class StatCmdSummariesTest : public ::testing::Test {
  protected:
   void AddSummary(const std::string event_name, pid_t tid, int cpu, uint64_t count,
@@ -637,6 +682,7 @@
   std::unique_ptr<CounterSummaries> summaries_;
 };
 
+// @CddTest = 6.1/C-0-2
 TEST_F(StatCmdSummariesTest, task_clock_comment) {
   AddSummary("task-clock", -1, -1, 1e9, 0);
   AddSummary("task-clock", 0, -1, 2e9, 0);
@@ -648,6 +694,7 @@
   ASSERT_EQ(*GetComment(3), "3.000000 cpus used");
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(StatCmdSummariesTest, cpu_cycles_comment) {
   AddSummary("cpu-cycles", -1, -1, 100, 100);
   AddSummary("cpu-cycles", 0, -1, 200, 100);
@@ -659,6 +706,7 @@
   ASSERT_EQ(*GetComment(3), "3.000000 GHz");
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(StatCmdSummariesTest, rate_comment) {
   AddSummary("branch-misses", -1, -1, 1e9, 1e9);
   AddSummary("branch-misses", 0, -1, 1e6, 1e9);
diff --git a/simpleperf/cmd_trace_sched_test.cpp b/simpleperf/cmd_trace_sched_test.cpp
index 11ba3ba..a48f97c 100644
--- a/simpleperf/cmd_trace_sched_test.cpp
+++ b/simpleperf/cmd_trace_sched_test.cpp
@@ -43,10 +43,12 @@
   return CreateCommandInstance("trace-sched");
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(trace_sched_cmd, smoke) {
   TEST_IN_ROOT({ ASSERT_TRUE(TraceSchedCmd()->Run({"--duration", "1"})); });
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(trace_sched_cmd, report_smoke) {
   CaptureStdout capture;
   ASSERT_TRUE(capture.Start());
diff --git a/simpleperf/command_test.cpp b/simpleperf/command_test.cpp
index 392ec8a..a8c5965 100644
--- a/simpleperf/command_test.cpp
+++ b/simpleperf/command_test.cpp
@@ -27,6 +27,7 @@
   bool Run(const std::vector<std::string>&) override { return true; }
 };
 
+// @CddTest = 6.1/C-0-2
 TEST(command, CreateCommandInstance) {
   ASSERT_TRUE(CreateCommandInstance("mock1") == nullptr);
   RegisterCommand("mock1", [] { return std::unique_ptr<Command>(new MockCommand); });
@@ -35,6 +36,7 @@
   ASSERT_TRUE(CreateCommandInstance("mock1") == nullptr);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(command, GetAllCommands) {
   size_t command_count = GetAllCommandNames().size();
   RegisterCommand("mock1", [] { return std::unique_ptr<Command>(new MockCommand); });
@@ -43,6 +45,7 @@
   ASSERT_EQ(command_count, GetAllCommandNames().size());
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(command, GetValueForOption) {
   MockCommand command;
   uint64_t value;
@@ -70,6 +73,7 @@
   ASSERT_DOUBLE_EQ(double_value, 3.2);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(command, PreprocessOptions) {
   MockCommand cmd;
   OptionValueMap options;
@@ -156,6 +160,7 @@
                                      &ordered_options, nullptr));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(command, OptionValueMap) {
   OptionValue value;
   value.uint_value = 10;
diff --git a/simpleperf/doc/scripts_reference.md b/simpleperf/doc/scripts_reference.md
index d118ed2..af74458 100644
--- a/simpleperf/doc/scripts_reference.md
+++ b/simpleperf/doc/scripts_reference.md
@@ -151,6 +151,9 @@
 # Adding disassembly for all binaries can cost a lot of time. So we can choose to only add
 # disassembly for selected binaries.
 $ ./report_html.py --add_disassembly --binary_filter libgame.so
+# Add disassembly and source code for binaries belonging to an app with package name
+# com.example.myapp.
+$ ./report_html.py --add_source_code --add_disassembly --binary_filter com.example.myapp
 
 # report_html.py accepts more than one recording data file.
 $ ./report_html.py -i perf1.data perf2.data
diff --git a/simpleperf/dso.cpp b/simpleperf/dso.cpp
index 607bf7d..1380ada 100644
--- a/simpleperf/dso.cpp
+++ b/simpleperf/dso.cpp
@@ -875,8 +875,8 @@
     if (elf) {
       status = elf->ParseSymbols(symbol_callback);
     }
-    ReportReadElfSymbolResult(status, path_, GetDebugFilePath(),
-                              symbols_.empty() ? android::base::WARNING : android::base::DEBUG);
+    // Don't warn when a kernel module is missing. As a backup, we read symbols from /proc/kallsyms.
+    ReportReadElfSymbolResult(status, path_, GetDebugFilePath(), android::base::DEBUG);
     SortAndFixSymbols(symbols);
     return symbols;
   }
@@ -897,6 +897,10 @@
     // and its vaddr_in_file from the kernel module file. Then other symbols in .text section can
     // be mapped in the same way. Below we use the second method.
 
+    if (!IsRegularFile(GetDebugFilePath())) {
+      return;
+    }
+
     // 1. Select a module symbol in /proc/kallsyms.
     kernel_dso_->LoadSymbols();
     const auto& kernel_symbols = kernel_dso_->GetSymbols();
diff --git a/simpleperf/dso_test.cpp b/simpleperf/dso_test.cpp
index 11bcde1..f9199e4 100644
--- a/simpleperf/dso_test.cpp
+++ b/simpleperf/dso_test.cpp
@@ -30,6 +30,7 @@
 using namespace simpleperf;
 using namespace simpleperf_dso_impl;
 
+// @CddTest = 6.1/C-0-2
 TEST(DebugElfFileFinder, use_build_id_list) {
   // Create a temp symdir with build_id_list.
   TemporaryDir tmpdir;
@@ -57,6 +58,7 @@
   return result;
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(DebugElfFileFinder, concatenating_symfs_dir) {
   DebugElfFileFinder finder;
   ASSERT_TRUE(finder.SetSymFsDir(GetTestDataDir()));
@@ -73,6 +75,7 @@
             GetTestDataDir() + apk_path + "!/" + NATIVELIB_IN_APK);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(DebugElfFileFinder, use_vdso) {
   DebugElfFileFinder finder;
   std::string fake_vdso32 = "fake_vdso32";
@@ -84,6 +87,7 @@
   ASSERT_EQ(finder.FindDebugFile("[vdso]", true, build_id), fake_vdso64);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(DebugElfFileFinder, add_symbol_dir) {
   DebugElfFileFinder finder;
   ASSERT_FALSE(finder.AddSymbolDir(GetTestDataDir() + "dir_not_exist"));
@@ -94,6 +98,7 @@
             symfs_dir + OS_PATH_SEPARATOR + "elf_for_build_id_check");
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(DebugElfFileFinder, build_id_list) {
   DebugElfFileFinder finder;
   // Find file in symfs dir with correct build_id_list.
@@ -109,6 +114,7 @@
   ASSERT_EQ(finder.FindDebugFile("elf", false, CHECK_ELF_FILE_BUILD_ID), "elf");
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(DebugElfFileFinder, no_build_id) {
   DebugElfFileFinder finder;
   // If not given a build id, we should match an elf in symfs without build id.
@@ -118,6 +124,7 @@
   ASSERT_EQ(finder.FindDebugFile("elf", false, build_id), symfs_dir + OS_PATH_SEPARATOR + "elf");
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(DebugElfFileFinder, find_basename_in_symfs_dir) {
   DebugElfFileFinder finder;
   // Find normal elf file.
@@ -136,6 +143,7 @@
             symfs_dir + OS_PATH_SEPARATOR + "elf");
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(DebugElfFileFinder, build_id_mismatch) {
   DebugElfFileFinder finder;
   finder.SetSymFsDir(GetTestDataDir());
@@ -148,6 +156,7 @@
   ASSERT_NE(stderr_output.find("build id mismatch"), std::string::npos);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(dso, dex_file_dso) {
 #if defined(__linux__)
   for (DsoType dso_type : {DSO_DEX_FILE, DSO_ELF_FILE}) {
@@ -177,6 +186,7 @@
 #endif  // defined(__linux__)
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(dso, dex_file_offsets) {
   std::unique_ptr<Dso> dso = Dso::CreateDso(DSO_DEX_FILE, "");
   ASSERT_TRUE(dso);
@@ -186,6 +196,7 @@
   ASSERT_EQ(*dso->DexFileOffsets(), std::vector<uint64_t>({0x1, 0x2, 0x3, 0x4, 0x5}));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(dso, embedded_elf) {
   const std::string file_path = GetUrlInApk(GetTestData(APK_FILE), NATIVELIB_IN_APK);
   std::unique_ptr<Dso> dso = Dso::CreateDso(DSO_ELF_FILE, file_path);
@@ -205,12 +216,14 @@
   ASSERT_EQ(build_id, native_lib_build_id);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(dso, IpToVaddrInFile) {
   std::unique_ptr<Dso> dso = Dso::CreateDso(DSO_ELF_FILE, GetTestData("libc.so"));
   ASSERT_TRUE(dso);
   ASSERT_EQ(0xa5140, dso->IpToVaddrInFile(0xe9201140, 0xe9201000, 0xa5000));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(dso, kernel_address_randomization) {
   // Use ELF_FILE as a fake kernel vmlinux.
   const std::string vmlinux_path = GetTestData(ELF_FILE);
@@ -234,6 +247,7 @@
   ASSERT_STREQ(symbol->Name(), "GlobalFunc");
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(dso, find_vmlinux_in_symdirs) {
   // Create a symdir.
   TemporaryDir tmpdir;
@@ -260,6 +274,7 @@
   ASSERT_EQ(0x400927, dso->IpToVaddrInFile(0x800527, 0x800000, 0));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(dso, kernel_module) {
   // Test finding debug files for kernel modules.
   Dso::SetSymFsDir(GetTestDataDir());
@@ -272,14 +287,16 @@
   ASSERT_EQ(dso->GetDebugFilePath(), GetTestData(ELF_FILE));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(dso, kernel_module_CalculateMinVaddr) {
   // Create fake Dso objects.
   auto kernel_dso = Dso::CreateDso(DSO_KERNEL, DEFAULT_KERNEL_MMAP_NAME);
   ASSERT_TRUE(kernel_dso);
   const uint64_t module_memory_start = 0xffffffa9bc790000ULL;
   const uint64_t module_memory_size = 0x8d7000ULL;
+  TemporaryFile tmpfile;
   auto module_dso =
-      Dso::CreateKernelModuleDso("fake_module.ko", module_memory_start,
+      Dso::CreateKernelModuleDso(tmpfile.path, module_memory_start,
                                  module_memory_start + module_memory_size, kernel_dso.get());
   ASSERT_TRUE(module_dso);
 
@@ -302,6 +319,7 @@
   ASSERT_EQ(module_dso->IpToVaddrInFile(0xffffffa9bc7a64e8ULL, module_memory_start, 0), 0x144e8);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(dso, symbol_map_file) {
   auto dso = Dso::CreateDso(DSO_SYMBOL_MAP_FILE, "perf-123.map");
   ASSERT_TRUE(dso);
@@ -310,6 +328,7 @@
   ASSERT_EQ(0x12345678, dso->IpToVaddrInFile(0x12345678, 0xe9201000, 0xa5000));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(dso, FunctionName) {
   Symbol symbol = Symbol("void ctep.v(cteo, ctgc, ctbn)", 0x0, 0x1);
   ASSERT_EQ(symbol.FunctionName(), "ctep.v");
@@ -319,6 +338,7 @@
   ASSERT_EQ(symbol.FunctionName(), "ctep.v");
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(dso, search_debug_file_only_when_needed) {
   Dso::SetBuildIds({std::make_pair("/elf", BuildId("1b12a384a9f4a3f3659b7171ca615dbec3a81f71"))});
   Dso::SetSymFsDir(GetTestDataDir());
@@ -330,6 +350,7 @@
   capture.Stop();
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(dso, read_symbol_warning) {
   {
     // Don't warn when the file may not be an ELF file.
@@ -370,6 +391,7 @@
   }
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(dso, demangle) {
   ASSERT_EQ(Dso::Demangle("main"), "main");
   ASSERT_EQ(Dso::Demangle("_ZN4main4main17h2a68d4d833d7495aE"), "main::main::h2a68d4d833d7495a");
diff --git a/simpleperf/environment.cpp b/simpleperf/environment.cpp
index 88587dc..55074d8 100644
--- a/simpleperf/environment.cpp
+++ b/simpleperf/environment.cpp
@@ -75,6 +75,9 @@
 
 static void GetAllModuleFiles(const std::string& path,
                               std::unordered_map<std::string, std::string>* module_file_map) {
+  if (!IsDir(path)) {
+    return;
+  }
   for (const auto& name : GetEntriesInDir(path)) {
     std::string entry_path = path + "/" + name;
     if (IsRegularFile(entry_path) && android::base::EndsWith(name, ".ko")) {
@@ -94,9 +97,13 @@
   }
   std::unordered_map<std::string, std::string> module_file_map;
 #if defined(__ANDROID__)
-  // Search directories listed in "File locations" section in
-  // https://source.android.com/devices/architecture/kernel/modular-kernels.
-  for (const auto& path : {"/vendor/lib/modules", "/odm/lib/modules", "/lib/modules"}) {
+  // On Android, kernel modules are stored in /system/lib/modules, /vendor/lib/modules,
+  // /odm/lib/modules.
+  // See https://source.android.com/docs/core/architecture/partitions/gki-partitions and
+  // https://source.android.com/docs/core/architecture/partitions/vendor-odm-dlkm-partition.
+  // They can also be stored in vendor_kernel_ramdisk.img, which isn't accessible from userspace.
+  // See https://source.android.com/docs/core/architecture/kernel/kernel-module-support.
+  for (const auto& path : {"/system/lib/modules", "/vendor/lib/modules", "/odm/lib/modules"}) {
     GetAllModuleFiles(path, &module_file_map);
   }
 #else
diff --git a/simpleperf/environment_test.cpp b/simpleperf/environment_test.cpp
index 87c4998..49a9bb5 100644
--- a/simpleperf/environment_test.cpp
+++ b/simpleperf/environment_test.cpp
@@ -29,6 +29,7 @@
 namespace fs = std::filesystem;
 using namespace simpleperf;
 
+// @CddTest = 6.1/C-0-2
 TEST(environment, PrepareVdsoFile) {
   std::string content;
   ASSERT_TRUE(android::base::ReadFileToString("/proc/self/maps", &content));
@@ -46,6 +47,7 @@
   ASSERT_NE(dso->GetDebugFilePath(), "[vdso]");
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(environment, GetHardwareFromCpuInfo) {
   std::string cpu_info =
       "CPU revision : 10\n\n"
@@ -54,6 +56,7 @@
             GetHardwareFromCpuInfo(cpu_info));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(environment, MappedFileOnlyExistInMemory) {
   ASSERT_TRUE(MappedFileOnlyExistInMemory(""));
   ASSERT_TRUE(MappedFileOnlyExistInMemory("[stack]"));
@@ -66,6 +69,7 @@
   ASSERT_FALSE(MappedFileOnlyExistInMemory("/system/lib64/libc.so"));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(environment, SetPerfEventLimits) {
 #if defined(__ANDROID__)
   if (GetAndroidVersion() <= kAndroidVersionP) {
@@ -101,10 +105,12 @@
 #endif
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(environment, GetKernelVersion) {
   ASSERT_TRUE(GetKernelVersion());
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(environment, GetModuleBuildId) {
   BuildId build_id;
   fs::path dir(GetTestData("sysfs/module/fake_kernel_module/notes"));
@@ -114,6 +120,7 @@
   ASSERT_EQ(build_id, BuildId("3e0ba155286f3454"));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(environment, GetKernelAndModuleMmaps) {
   TEST_REQUIRE_ROOT();
   KernelMmap kernel_mmap;
@@ -124,12 +131,14 @@
   ASSERT_GT(kernel_mmap.start_addr, 0);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(environment, GetProcessUid) {
   std::optional<uid_t> uid = GetProcessUid(getpid());
   ASSERT_TRUE(uid.has_value());
   ASSERT_EQ(uid.value(), getuid());
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(environment, GetAppType) {
   TEST_REQUIRE_APPS();
   ASSERT_EQ(GetAppType("com.android.simpleperf.debuggable"), "debuggable");
@@ -137,12 +146,14 @@
   ASSERT_EQ(GetAppType("com.android.simpleperf.app_not_exist"), "not_exist");
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(environment, GetMemorySize) {
   auto value = GetMemorySize();
   ASSERT_TRUE(value);
   ASSERT_GT(value.value(), 0);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(environment, GetARMCpuModels) {
 #if defined(__aarch64__) && defined(__ANDROID__)
   auto models = GetARMCpuModels();
diff --git a/simpleperf/event_selection_set_test.cpp b/simpleperf/event_selection_set_test.cpp
index 2cf0e0a..e60d81a 100644
--- a/simpleperf/event_selection_set_test.cpp
+++ b/simpleperf/event_selection_set_test.cpp
@@ -20,6 +20,7 @@
 
 using namespace simpleperf;
 
+// @CddTest = 6.1/C-0-2
 TEST(EventSelectionSet, set_sample_rate_for_new_events) {
   EventSelectionSet event_selection_set(false);
   ASSERT_TRUE(event_selection_set.AddEventType("cpu-clock:u"));
@@ -43,6 +44,7 @@
   ASSERT_EQ(attrs[3].attr.sample_freq, 200);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(EventSelectionSet, add_event_with_sample_rate) {
   EventSelectionSet event_selection_set(false);
   ASSERT_TRUE(event_selection_set.AddEventType("cpu-clock:u"));
@@ -57,6 +59,7 @@
   ASSERT_EQ(attrs[1].attr.sample_period, 1);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(EventSelectionSet, set_cpus_for_new_events) {
   EventSelectionSet event_selection_set(false);
   std::vector<int> online_cpus = GetOnlineCpus();
diff --git a/simpleperf/event_type.cpp b/simpleperf/event_type.cpp
index 0d10d12..d837914 100644
--- a/simpleperf/event_type.cpp
+++ b/simpleperf/event_type.cpp
@@ -104,7 +104,11 @@
  protected:
   void LoadTypes() override {
     for (const auto& line : android::base::Split(s_, "\n")) {
-      std::vector<std::string> items = android::base::Split(line, " ");
+      std::string str = android::base::Trim(line);
+      if (str.empty()) {
+        continue;
+      }
+      std::vector<std::string> items = android::base::Split(str, " ");
       CHECK_EQ(items.size(), 2u);
       std::string event_name = items[0];
       uint64_t id;
diff --git a/simpleperf/event_type.h b/simpleperf/event_type.h
index 14863ca..d85f71d 100644
--- a/simpleperf/event_type.h
+++ b/simpleperf/event_type.h
@@ -55,6 +55,7 @@
   bool IsHardwareEvent() const {
     return type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE || type == PERF_TYPE_RAW;
   }
+  bool IsTracepointEvent() const { return type == PERF_TYPE_TRACEPOINT; }
 
   std::vector<int> GetPmuCpumask();
 
diff --git a/simpleperf/kallsyms_test.cpp b/simpleperf/kallsyms_test.cpp
index cacd163..d2bc858 100644
--- a/simpleperf/kallsyms_test.cpp
+++ b/simpleperf/kallsyms_test.cpp
@@ -39,6 +39,7 @@
          ModulesMatch(sym1.module, sym2.module);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(kallsyms, ProcessKernelSymbols) {
   std::string data =
       "ffffffffa005c4e4 d __warned.41698   [libsas]\n"
@@ -64,6 +65,7 @@
       data, std::bind(&KernelSymbolsMatch, std::placeholders::_1, expected_symbol)));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(kallsyms, ProcessKernelSymbols_ignore_arm_mapping_symbols) {
   std::string data =
       "aaaaaaaaaaaaaaaa t $x.9 [coresight_etm4x]\n"
@@ -84,17 +86,20 @@
 }
 
 #if defined(__ANDROID__)
+// @CddTest = 6.1/C-0-2
 TEST(kallsyms, GetKernelStartAddress) {
   TEST_REQUIRE_ROOT();
   ASSERT_NE(GetKernelStartAddress(), 0u);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(kallsyms, LoadKernelSymbols) {
   TEST_REQUIRE_ROOT();
   std::string kallsyms;
   ASSERT_TRUE(LoadKernelSymbols(&kallsyms));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(kallsyms, print_warning) {
   TEST_REQUIRE_NON_ROOT();
   const std::string warning_msg = "Access to kernel symbol addresses is restricted.";
diff --git a/simpleperf/perf_regs_test.cpp b/simpleperf/perf_regs_test.cpp
index 0af9747..bc33ca9 100644
--- a/simpleperf/perf_regs_test.cpp
+++ b/simpleperf/perf_regs_test.cpp
@@ -20,6 +20,7 @@
 
 using namespace simpleperf;
 
+// @CddTest = 6.1/C-0-2
 TEST(RegSet, arch) {
   ArchType arch_pairs[3][2] = {
       {ARCH_X86_32, ARCH_X86_64},
diff --git a/simpleperf/read_apk_test.cpp b/simpleperf/read_apk_test.cpp
index e4dd71f..c0be177 100644
--- a/simpleperf/read_apk_test.cpp
+++ b/simpleperf/read_apk_test.cpp
@@ -22,6 +22,7 @@
 
 using namespace simpleperf;
 
+// @CddTest = 6.1/C-0-2
 TEST(read_apk, FindElfInApkByOffset) {
   ApkInspector inspector;
   ASSERT_TRUE(inspector.FindElfInApkByOffset("/dev/null", 0) == nullptr);
@@ -36,6 +37,7 @@
   ASSERT_EQ(NATIVELIB_SIZE_IN_APK, ee->entry_size());
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(read_apk, FindElfInApkByName) {
   ASSERT_TRUE(ApkInspector::FindElfInApkByName("/dev/null", "") == nullptr);
   ASSERT_TRUE(ApkInspector::FindElfInApkByName(GetTestData(APK_FILE), "") == nullptr);
@@ -45,6 +47,7 @@
   ASSERT_EQ(NATIVELIB_SIZE_IN_APK, ee->entry_size());
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(read_apk, ParseExtractedInMemoryPath) {
   std::string zip_path;
   std::string entry_name;
diff --git a/simpleperf/read_dex_file_test.cpp b/simpleperf/read_dex_file_test.cpp
index 843a964..a9860f8 100644
--- a/simpleperf/read_dex_file_test.cpp
+++ b/simpleperf/read_dex_file_test.cpp
@@ -27,6 +27,7 @@
 
 using namespace simpleperf;
 
+// @CddTest = 6.1/C-0-2
 TEST(read_dex_file, smoke) {
   std::vector<Symbol> symbols;
   auto symbol_callback = [&](DexFileSymbol* symbol) {
diff --git a/simpleperf/read_elf_test.cpp b/simpleperf/read_elf_test.cpp
index e2a2cd8..709205a 100644
--- a/simpleperf/read_elf_test.cpp
+++ b/simpleperf/read_elf_test.cpp
@@ -32,6 +32,7 @@
 
 using namespace simpleperf;
 
+// @CddTest = 6.1/C-0-2
 TEST(read_elf, GetBuildIdFromNoteSection) {
   BuildId build_id;
   std::vector<char> data;
@@ -62,6 +63,7 @@
   }
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(read_elf, GetBuildIdFromElfFile) {
   BuildId build_id;
   ElfStatus status;
@@ -71,6 +73,7 @@
   ASSERT_EQ(build_id, BuildId(elf_file_build_id));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(read_elf, GetBuildIdFromEmbeddedElfFile) {
   BuildId build_id;
   ElfStatus status;
@@ -103,6 +106,7 @@
   CheckFunctionSymbols(symbols);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(read_elf, parse_symbols_from_elf_file_with_correct_build_id) {
   std::map<std::string, ElfFileSymbol> symbols;
   ElfStatus status;
@@ -113,6 +117,7 @@
   CheckElfFileSymbols(symbols);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(read_elf, parse_symbols_from_elf_file_without_build_id) {
   std::map<std::string, ElfFileSymbol> symbols;
   ElfStatus status;
@@ -133,6 +138,7 @@
   CheckElfFileSymbols(symbols);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(read_elf, parse_symbols_from_elf_file_with_wrong_build_id) {
   BuildId build_id("01010101010101010101");
   std::map<std::string, ElfFileSymbol> symbols;
@@ -141,6 +147,7 @@
   ASSERT_EQ(ElfStatus::BUILD_ID_MISMATCH, status);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(read_elf, ParseSymbolsFromEmbeddedElfFile) {
   std::map<std::string, ElfFileSymbol> symbols;
   ElfStatus status;
@@ -152,6 +159,7 @@
   CheckElfFileSymbols(symbols);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(read_elf, ParseSymbolFromMiniDebugInfoElfFile) {
   std::map<std::string, ElfFileSymbol> symbols;
   ElfStatus status;
@@ -162,6 +170,7 @@
   CheckFunctionSymbols(symbols);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(read_elf, arm_mapping_symbol) {
   ASSERT_TRUE(IsArmMappingSymbol("$a"));
   ASSERT_FALSE(IsArmMappingSymbol("$b"));
@@ -169,6 +178,7 @@
   ASSERT_FALSE(IsArmMappingSymbol("$a_no_dot"));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(read_elf, ElfFile_Open) {
   auto IsValidElfPath = [](const std::string& path) {
     ElfStatus status;
@@ -183,6 +193,7 @@
   ASSERT_EQ(ElfStatus::NO_ERROR, IsValidElfPath(GetTestData(ELF_FILE)));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(read_elf, check_symbol_for_plt_section) {
   std::map<std::string, ElfFileSymbol> symbols;
   ElfStatus status;
@@ -193,6 +204,7 @@
   ASSERT_NE(symbols.find("@plt"), symbols.end());
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(read_elf, read_elf_with_broken_section_table) {
   std::string elf_path = GetTestData("libsgmainso-6.4.36.so");
   std::map<std::string, ElfFileSymbol> symbols;
@@ -211,6 +223,7 @@
   ASSERT_EQ(file_offset_of_min_vaddr, 0u);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(read_elf, ReadMinExecutableVaddr) {
   ElfStatus status;
   auto elf = ElfFile::Open(GetTestData("libc.so"), &status);
@@ -221,6 +234,7 @@
   ASSERT_EQ(file_offset_of_min_vaddr, 0x29000u);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(read_elf, NoUndefinedSymbol) {
   // Check if we read undefined symbols (like dlerror) from libc.so.
   bool has_dlerror = false;
@@ -237,6 +251,7 @@
   ASSERT_FALSE(has_dlerror);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(read_elf, VaddrToOff) {
   auto elf = ElfFile::Open(GetTestData(ELF_FILE));
   ASSERT_TRUE(elf != nullptr);
@@ -247,6 +262,7 @@
   ASSERT_FALSE(elf->VaddrToOff(0x420000, &off));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(read_elf, GetSectionHeader) {
   auto elf = ElfFile::Open(GetTestData(ELF_FILE));
   ASSERT_TRUE(elf != nullptr);
diff --git a/simpleperf/read_symbol_map_test.cpp b/simpleperf/read_symbol_map_test.cpp
index 9a5ac39..4365fc9 100644
--- a/simpleperf/read_symbol_map_test.cpp
+++ b/simpleperf/read_symbol_map_test.cpp
@@ -25,6 +25,7 @@
 
 using namespace simpleperf;
 
+// @CddTest = 6.1/C-0-2
 TEST(read_symbol_map, smoke) {
   std::string content(
       "\n"  // skip
@@ -62,6 +63,7 @@
   ASSERT_STREQ("six six", symbols[3].Name());
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(read_symbol_map, v8_basic_perf_prof) {
   // Interesting sample of jitted function names generated by V8 running the
   // JetStream2 benchmark.
diff --git a/simpleperf/record_file_test.cpp b/simpleperf/record_file_test.cpp
index e43e4bd..7967362 100644
--- a/simpleperf/record_file_test.cpp
+++ b/simpleperf/record_file_test.cpp
@@ -35,6 +35,7 @@
 using namespace simpleperf;
 using namespace simpleperf::PerfFileFormat;
 
+// @CddTest = 6.1/C-0-2
 class RecordFileTest : public ::testing::Test {
  protected:
   void SetUp() override { close(tmpfile_.release()); }
@@ -54,6 +55,7 @@
   EventAttrIds attr_ids_;
 };
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordFileTest, smoke) {
   // Write to a record file.
   std::unique_ptr<RecordFileWriter> writer = RecordFileWriter::CreateInstance(tmpfile_.path);
@@ -102,6 +104,7 @@
   ASSERT_TRUE(reader->Close());
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordFileTest, record_more_than_one_attr) {
   // Write to a record file.
   std::unique_ptr<RecordFileWriter> writer = RecordFileWriter::CreateInstance(tmpfile_.path);
@@ -126,6 +129,7 @@
   }
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordFileTest, write_meta_info_feature_section) {
   // Write to a record file.
   std::unique_ptr<RecordFileWriter> writer = RecordFileWriter::CreateInstance(tmpfile_.path);
@@ -150,6 +154,7 @@
   ASSERT_EQ(reader->GetMetaInfoFeature(), info_map);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordFileTest, write_debug_unwind_feature_section) {
   // Write to a record file.
   std::unique_ptr<RecordFileWriter> writer = RecordFileWriter::CreateInstance(tmpfile_.path);
@@ -180,6 +185,7 @@
   }
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordFileTest, write_file2_feature_section) {
   // Write to a record file.
   std::unique_ptr<RecordFileWriter> writer = RecordFileWriter::CreateInstance(tmpfile_.path);
@@ -254,4 +260,4 @@
   }
   ASSERT_FALSE(error);
   ASSERT_EQ(file_id, files.size());
-}
\ No newline at end of file
+}
diff --git a/simpleperf/record_lib_test.cpp b/simpleperf/record_lib_test.cpp
index 4c1b7e8..15aa926 100644
--- a/simpleperf/record_lib_test.cpp
+++ b/simpleperf/record_lib_test.cpp
@@ -22,6 +22,7 @@
 
 using namespace simpleperf;
 
+// @CddTest = 6.1/C-0-2
 TEST(get_all_events, smoke) {
   std::vector<std::string> events = GetAllEvents();
   ASSERT_GT(events.size(), 0u);
@@ -36,6 +37,7 @@
   }
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(counter, add_event) {
   std::unique_ptr<PerfEventSet> perf(
       PerfEventSet::CreateInstance(PerfEventSet::Type::kPerfForCounting));
@@ -61,6 +63,7 @@
   }
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(counter, different_targets) {
   auto test_function = [](std::function<void(PerfEventSet*)> set_target_func) {
     std::unique_ptr<PerfEventSet> perf(
@@ -87,6 +90,7 @@
       [](PerfEventSet* perf) { ASSERT_TRUE(perf->MonitorThreadsInCurrentProcess({getpid()})); });
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(counter, start_stop_multiple_times) {
   const size_t TEST_COUNT = 10;
   std::unique_ptr<PerfEventSet> perf(
@@ -116,6 +120,7 @@
   }
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(counter, no_change_after_stop) {
   std::unique_ptr<PerfEventSet> perf(
       PerfEventSet::CreateInstance(PerfEventSet::Type::kPerfForCounting));
diff --git a/simpleperf/record_test.cpp b/simpleperf/record_test.cpp
index bca0b7f..ed43750 100644
--- a/simpleperf/record_test.cpp
+++ b/simpleperf/record_test.cpp
@@ -23,6 +23,7 @@
 
 using namespace simpleperf;
 
+// @CddTest = 6.1/C-0-2
 class RecordTest : public ::testing::Test {
  protected:
   virtual void SetUp() {
@@ -42,16 +43,19 @@
   perf_event_attr event_attr;
 };
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordTest, MmapRecordMatchBinary) {
   MmapRecord record(event_attr, true, 1, 2, 0x1000, 0x2000, 0x3000, "MmapRecord", 0);
   CheckRecordMatchBinary(record);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordTest, CommRecordMatchBinary) {
   CommRecord record(event_attr, 1, 2, "CommRecord", 0, 7);
   CheckRecordMatchBinary(record);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordTest, SampleRecordMatchBinary) {
   event_attr.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_TIME | PERF_SAMPLE_ID |
                            PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD | PERF_SAMPLE_CALLCHAIN;
@@ -59,6 +63,7 @@
   CheckRecordMatchBinary(record);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordTest, SampleRecord_exclude_kernel_callchain) {
   SampleRecord r(event_attr, 0, 1, 0, 0, 0, 0, 0, {}, {}, {}, 0);
   ASSERT_TRUE(r.ExcludeKernelCallChain());
@@ -103,6 +108,7 @@
                                     {}, 0));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordTest, SampleRecord_ReplaceRegAndStackWithCallChain) {
   event_attr.sample_type |= PERF_SAMPLE_CALLCHAIN;
   std::vector<std::vector<uint64_t>> user_ip_tests = {
@@ -130,6 +136,7 @@
   }
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordTest, SampleRecord_UpdateUserCallChain) {
   event_attr.sample_type |= PERF_SAMPLE_CALLCHAIN | PERF_SAMPLE_REGS_USER | PERF_SAMPLE_STACK_USER;
   SampleRecord r(event_attr, 0, 1, 2, 3, 4, 5, 6, {}, {1, PERF_CONTEXT_USER, 2}, {}, 0);
@@ -140,6 +147,7 @@
   CheckRecordEqual(r, expected);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordTest, SampleRecord_AdjustCallChainGeneratedByKernel) {
   event_attr.sample_type |= PERF_SAMPLE_CALLCHAIN | PERF_SAMPLE_REGS_USER | PERF_SAMPLE_STACK_USER;
   SampleRecord r(event_attr, 0, 1, 2, 3, 4, 5, 6, {}, {1, 5, 0, PERF_CONTEXT_USER, 6, 0}, {}, 0);
@@ -154,6 +162,7 @@
   CheckRecordEqual(r, expected);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordTest, SampleRecord_PerfSampleReadData) {
   event_attr.sample_type |= PERF_SAMPLE_READ;
   event_attr.read_format =
@@ -180,6 +189,7 @@
   CheckRecordMatchBinary(r2);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordTest, CommRecord) {
   CommRecord r(event_attr, 1, 2, "init_name", 3, 4);
   size_t record_size = r.size();
@@ -194,6 +204,7 @@
   CheckRecordMatchBinary(r);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(RecordTest, DebugRecord) {
   DebugRecord r(1234, "hello");
   ASSERT_EQ(r.size() % sizeof(uint64_t), 0);
diff --git a/simpleperf/report_utils_test.cpp b/simpleperf/report_utils_test.cpp
index ad4b9df..0d96d7d 100644
--- a/simpleperf/report_utils_test.cpp
+++ b/simpleperf/report_utils_test.cpp
@@ -27,6 +27,7 @@
 
 using namespace simpleperf;
 
+// @CddTest = 6.1/C-0-2
 TEST(ProguardMappingRetrace, smoke) {
   TemporaryFile tmpfile;
   close(tmpfile.release());
@@ -151,6 +152,7 @@
   };
 };
 
+// @CddTest = 6.1/C-0-2
 TEST_F(CallChainReportBuilderTest, default_option) {
   // Test default option: remove_art_frame = true, convert_jit_frame = true.
   // The callchain shouldn't include interpreter frames. And the JIT frame is
@@ -170,6 +172,7 @@
   ASSERT_EQ(entries[1].execution_type, CallChainExecutionType::JIT_JVM_METHOD);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(CallChainReportBuilderTest, not_convert_jit_frame) {
   // Test option: remove_art_frame = true, convert_jit_frame = false.
   // The callchain shouldn't include interpreter frames. And the JIT frame isn't
@@ -190,6 +193,7 @@
   ASSERT_EQ(entries[1].execution_type, CallChainExecutionType::JIT_JVM_METHOD);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(CallChainReportBuilderTest, not_remove_art_frame) {
   // Test option: remove_art_frame = false, convert_jit_frame = true.
   // The callchain should include interpreter frames. And the JIT frame is
@@ -222,6 +226,7 @@
   ASSERT_EQ(entries[5].execution_type, CallChainExecutionType::JIT_JVM_METHOD);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(CallChainReportBuilderTest, remove_jit_frame_called_by_dex_frame) {
   // Test option: remove_art_frame = true, convert_jit_frame = true.
   // The callchain should remove the JIT frame called by a dex frame having the same symbol name.
@@ -242,6 +247,7 @@
   ASSERT_EQ(entries[0].execution_type, CallChainExecutionType::INTERPRETED_JVM_METHOD);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(CallChainReportBuilderTest, remove_art_frame_only_near_jvm_method) {
   // Test option: remove_art_frame = true, convert_jit_frame = true.
   // The callchain should not remove ART symbols not near a JVM method.
@@ -277,6 +283,7 @@
   ASSERT_EQ(entries[2].execution_type, CallChainExecutionType::INTERPRETED_JVM_METHOD);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(CallChainReportBuilderTest, keep_art_jni_method) {
   // Test option: remove_art_frame = true.
   // The callchain should remove art_jni_trampoline, but keep jni methods.
@@ -305,6 +312,7 @@
   ASSERT_EQ(entries[1].execution_type, CallChainExecutionType::INTERPRETED_JVM_METHOD);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(CallChainReportBuilderTest, add_proguard_mapping_file) {
   std::vector<uint64_t> fake_ips = {
       0x2200,  // 2200,  // obfuscated_class.obfuscated_java_method
@@ -364,6 +372,7 @@
   ASSERT_EQ(entries[2].execution_type, CallChainExecutionType::JIT_JVM_METHOD);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(CallChainReportBuilderTest, not_remove_synthesized_frame_by_default) {
   std::vector<uint64_t> fake_ips = {
       0x2200,  // 2200,  // obfuscated_class.obfuscated_java_method
@@ -400,6 +409,7 @@
   ASSERT_EQ(entries[1].execution_type, CallChainExecutionType::JIT_JVM_METHOD);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(CallChainReportBuilderTest, remove_synthesized_frame_with_env_variable) {
   // Windows doesn't support setenv and unsetenv. So don't test on it.
 #if !defined(__WIN32)
@@ -435,6 +445,7 @@
 #endif  // !defined(__WIN32)
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(CallChainReportBuilderTest, add_proguard_mapping_file_for_jit_method_with_signature) {
   std::vector<uint64_t> fake_ips = {
       0x3200,  // 3200,  // void ctep.v(cteo, ctgc, ctbn)
@@ -460,6 +471,7 @@
   ASSERT_EQ(entries[0].execution_type, CallChainExecutionType::JIT_JVM_METHOD);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(CallChainReportBuilderTest,
        add_proguard_mapping_file_for_compiled_java_method_with_signature) {
   TemporaryFile tmpfile;
@@ -492,6 +504,7 @@
   }
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(CallChainReportBuilderTest, convert_jit_frame_for_jit_method_with_signature) {
   std::vector<uint64_t> fake_ips = {
       0x2200,  // 2200,  // ctep.v
@@ -540,6 +553,7 @@
   ASSERT_EQ(entries[1].execution_type, CallChainExecutionType::JIT_JVM_METHOD);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(CallChainReportBuilderTest, remove_method_name) {
   // Test excluding method names.
   CallChainReportBuilder builder(thread_tree);
@@ -588,6 +602,7 @@
   ThreadTree thread_tree;
 };
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ThreadReportBuilderTest, no_setting) {
   ThreadReportBuilder builder;
   ThreadEntry* thread = thread_tree.FindThread(1);
@@ -595,6 +610,7 @@
   ASSERT_TRUE(IsReportEqual(report, ThreadReport(1, 1, "thread1")));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ThreadReportBuilderTest, aggregate_threads) {
   ThreadReportBuilder builder;
   ASSERT_TRUE(builder.AggregateThreads({"thread-pool.*"}));
@@ -609,6 +625,7 @@
   ASSERT_TRUE(IsReportEqual(report, ThreadReport(1, 2, "thread-pool.*")));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ThreadReportBuilderTest, aggregate_threads_bad_regex) {
   ThreadReportBuilder builder;
   ASSERT_FALSE(builder.AggregateThreads({"?thread-pool*"}));
diff --git a/simpleperf/sample_tree_test.cpp b/simpleperf/sample_tree_test.cpp
index bee187d..e2df1ce 100644
--- a/simpleperf/sample_tree_test.cpp
+++ b/simpleperf/sample_tree_test.cpp
@@ -132,6 +132,7 @@
   std::unique_ptr<TestSampleTreeBuilder> sample_tree_builder;
 };
 
+// @CddTest = 6.1/C-0-2
 TEST_F(SampleTreeTest, ip_in_map) {
   sample_tree_builder->AddSample(1, 1, 1, false);
   sample_tree_builder->AddSample(1, 1, 2, false);
@@ -142,6 +143,7 @@
   CheckSamples(expected_samples);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(SampleTreeTest, different_pid) {
   sample_tree_builder->AddSample(1, 1, 1, false);
   sample_tree_builder->AddSample(2, 2, 1, false);
@@ -152,6 +154,7 @@
   CheckSamples(expected_samples);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(SampleTreeTest, different_tid) {
   sample_tree_builder->AddSample(1, 1, 1, false);
   sample_tree_builder->AddSample(1, 11, 1, false);
@@ -162,6 +165,7 @@
   CheckSamples(expected_samples);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(SampleTreeTest, different_comm) {
   sample_tree_builder->AddSample(1, 1, 1, false);
   thread_tree.SetThreadName(1, 1, "p1t1_comm2");
@@ -173,6 +177,7 @@
   CheckSamples(expected_samples);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(SampleTreeTest, different_map) {
   sample_tree_builder->AddSample(1, 1, 1, false);
   sample_tree_builder->AddSample(1, 1, 6, false);
@@ -183,6 +188,7 @@
   CheckSamples(expected_samples);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(SampleTreeTest, unmapped_sample) {
   sample_tree_builder->AddSample(1, 1, 0, false);
   sample_tree_builder->AddSample(1, 1, 31, false);
@@ -194,6 +200,7 @@
   CheckSamples(expected_samples);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(SampleTreeTest, map_kernel) {
   sample_tree_builder->AddSample(1, 1, 10, true);
   sample_tree_builder->AddSample(1, 1, 10, false);
@@ -204,6 +211,7 @@
   CheckSamples(expected_samples);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(sample_tree, overlapped_map) {
   ThreadTree thread_tree;
   TestSampleTreeBuilder sample_tree_builder(&thread_tree);
@@ -226,6 +234,7 @@
   CheckSamples(sample_tree_builder.GetSamples(), expected_samples);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(thread_tree, symbol_ULLONG_MAX) {
   ThreadTree thread_tree;
   thread_tree.ShowIpForUnknownSymbol();
diff --git a/simpleperf/scripts/report_html.js b/simpleperf/scripts/report_html.js
index 94e8ae5..a3f899d 100644
--- a/simpleperf/scripts/report_html.js
+++ b/simpleperf/scripts/report_html.js
@@ -379,10 +379,10 @@
         };
         if (isClockEvent(this.eventInfo)) {
             this.getSampleWeight = function (eventCount) {
-                return (eventCount / 1000000.0).toFixed(3) + ' ms';
+                return (eventCount / 1000000.0).toFixed(3).toLocaleString() + ' ms';
             };
         } else {
-            this.getSampleWeight = (eventCount) => '' + eventCount;
+            this.getSampleWeight = (eventCount) => eventCount.toLocaleString();
         }
     }
 
@@ -622,10 +622,10 @@
             return (eventCount) => (eventCount * 100.0 / this.eventCount).toFixed(2) + '%';
         }
         if (this.curOption == 'event_count') {
-            return (eventCount) => '' + eventCount;
+            return (eventCount) => eventCount.toLocaleString();
         }
         if (this.curOption == 'event_count_in_ms') {
-            return (eventCount) => (eventCount / 1000000.0).toFixed(3);
+            return (eventCount) => (eventCount / 1000000.0).toFixed(3).toLocaleString();
         }
     }
 
@@ -706,7 +706,7 @@
                     data: data,
                     responsive: true,
                     columnDefs: [
-                        { orderSequence: [ 'desc' ], targets: [0, 1, 2] },
+                        { orderSequence: [ 'desc' ], className: 'textRight', targets: [0, 1, 2] },
                     ],
                 });
                 dataTable.column(7).visible(false);
@@ -1082,13 +1082,13 @@
         }
         if (this.curOption == 'event_count') {
             return function(eventCount, _) {
-                return '' + eventCount;
+                return eventCount.toLocaleString();
             };
         }
         if (this.curOption == 'event_count_in_ms') {
             return function(eventCount, _) {
                 let timeInMs = eventCount / 1000000.0;
-                return timeInMs.toFixed(3) + ' ms';
+                return timeInMs.toFixed(3).toLocaleString() + ' ms';
             };
         }
     }
@@ -1590,12 +1590,9 @@
             data.addColumn('string', 'Self');
             data.addColumn('string', 'Code');
             data.addRows(rows);
-            for (let i = 0; i < rows.length; ++i) {
-                data.setProperty(i, 0, 'className', 'colForLine');
-                for (let j = 1; j <= 2; ++j) {
-                    data.setProperty(i, j, 'className', 'colForCount');
-                }
-            }
+            data.setColumnProperty(0, 'className', 'colForLine');
+            data.setColumnProperty(1, 'className', 'colForCount');
+            data.setColumnProperty(2, 'className', 'colForCount');
             this.div.append(getHtml('pre', {text: sourceFile.path}));
             let wrapperDiv = $('<div>');
             wrapperDiv.appendTo(this.div);
@@ -1687,11 +1684,8 @@
         data.addColumn('string', 'Self');
         data.addColumn('string', 'Code');
         data.addRows(rows);
-        for (let i = 0; i < rows.length; ++i) {
-            for (let j = 0; j < 2; ++j) {
-                data.setProperty(i, j, 'className', 'colForCount');
-            }
-        }
+        data.setColumnProperty(0, 'className', 'colForCount');
+        data.setColumnProperty(1, 'className', 'colForCount');
         let wrapperDiv = $('<div>');
         wrapperDiv.appendTo(this.div);
         let table = new google.visualization.Table(wrapperDiv.get(0));
diff --git a/simpleperf/scripts/report_html.py b/simpleperf/scripts/report_html.py
index ba143fd..314a33f 100755
--- a/simpleperf/scripts/report_html.py
+++ b/simpleperf/scripts/report_html.py
@@ -982,10 +982,11 @@
         self.hw.open_tag('script').add(
             "google.charts.load('current', {'packages': ['corechart', 'table']});").close_tag()
         self.hw.open_tag('style', type='text/css').add("""
-            .colForLine { width: 50px; }
-            .colForCount { width: 100px; }
+            .colForLine { width: 50px; text-align: right; }
+            .colForCount { width: 100px; text-align: right; }
             .tableCell { font-size: 17px; }
             .boldTableCell { font-weight: bold; font-size: 17px; }
+            .textRight { text-align: right; }
             """).close_tag()
         self.hw.close_tag('head')
         self.hw.open_tag('body')
@@ -1027,7 +1028,10 @@
     parser.add_argument('--disassemble-job-size', type=int, default=1024*1024,
                         help='address range for one disassemble job')
     parser.add_argument('--binary_filter', nargs='+', help="""Annotate source code and disassembly
-                        only for selected binaries.""")
+                        only for selected binaries, whose recorded paths contains [BINARY_FILTER] as
+                        a substring. Example: to select binaries belonging to an app with package
+                        name 'com.example.myapp', use `--binary_filter com.example.myapp`.
+                        """)
     parser.add_argument(
         '-j', '--jobs', type=int, default=os.cpu_count(),
         help='Use multithreading to speed up disassembly and source code annotation.')
diff --git a/simpleperf/scripts/simpleperf_utils.py b/simpleperf/scripts/simpleperf_utils.py
index 90f94cf..e536b1b 100644
--- a/simpleperf/scripts/simpleperf_utils.py
+++ b/simpleperf/scripts/simpleperf_utils.py
@@ -844,6 +844,7 @@
                 real_path]
         if arch == 'arm' and 'llvm-objdump' in objdump_path:
             args += ['--print-imm-hex']
+        logging.debug('disassembling: %s', ' '.join(args))
         try:
             subproc = subprocess.Popen(args, stdout=subprocess.PIPE)
             (stdoutdata, _) = subproc.communicate()
diff --git a/simpleperf/test_util.cpp b/simpleperf/test_util.cpp
index 7e99b5d..42dee70 100644
--- a/simpleperf/test_util.cpp
+++ b/simpleperf/test_util.cpp
@@ -117,18 +117,23 @@
   return false;
 }
 
+bool IsInEmulator() {
+  std::string fingerprint = android::base::GetProperty("ro.system.build.fingerprint", "");
+  return android::base::StartsWith(fingerprint, "google/sdk_gphone") ||
+         android::base::StartsWith(fingerprint, "google/sdk_gpc") ||
+         android::base::StartsWith(fingerprint, "generic/cf") ||
+         android::base::StartsWith(fingerprint, "generic/aosp_cf");
+}
+
 bool HasHardwareCounter() {
   static int has_hw_counter = -1;
   if (has_hw_counter == -1) {
     has_hw_counter = 1;
     auto arch = GetTargetArch();
-    std::string fingerprint = android::base::GetProperty("ro.system.build.fingerprint", "");
-    bool is_emulator = android::base::StartsWith(fingerprint, "google/sdk_gphone") ||
-                       android::base::StartsWith(fingerprint, "google/sdk_gpc") ||
-                       android::base::StartsWith(fingerprint, "generic/cf");
+
     bool in_native_abi = IsInNativeAbi() == std::optional(true);
 
-    if (arch == ARCH_X86_64 || arch == ARCH_X86_32 || !in_native_abi || is_emulator) {
+    if (arch == ARCH_X86_64 || arch == ARCH_X86_32 || !in_native_abi || IsInEmulator()) {
       // On x86 and x86_64, or when we are not in native abi, it's likely to run on an emulator or
       // vm without hardware perf counters. It's hard to enumerate them all. So check the support
       // at runtime.
@@ -171,7 +176,12 @@
 bool HasTracepointEvents() {
   static int has_tracepoint_events = -1;
   if (has_tracepoint_events == -1) {
-    has_tracepoint_events = (GetTraceFsDir() != nullptr) ? 1 : 0;
+    has_tracepoint_events = 0;
+    if (const char* dir = GetTraceFsDir(); dir != nullptr) {
+      if (IsDir(std::string(dir) + "/events/sched/sched_switch")) {
+        has_tracepoint_events = 1;
+      }
+    }
   }
   return has_tracepoint_events == 1;
 }
diff --git a/simpleperf/test_util.h b/simpleperf/test_util.h
index 1648310..4264c9a 100644
--- a/simpleperf/test_util.h
+++ b/simpleperf/test_util.h
@@ -201,3 +201,5 @@
   std::vector<std::string> installed_packages_;
   std::unique_ptr<Workload> app_start_proc_;
 };
+
+bool IsInEmulator();
diff --git a/simpleperf/thread_tree_test.cpp b/simpleperf/thread_tree_test.cpp
index f5b71ec..7f1768e 100644
--- a/simpleperf/thread_tree_test.cpp
+++ b/simpleperf/thread_tree_test.cpp
@@ -22,6 +22,7 @@
 
 using namespace simpleperf;
 
+// @CddTest = 6.1/C-0-2
 class ThreadTreeTest : public ::testing::Test {
  protected:
   void AddMap(uint64_t start, uint64_t end, const std::string& name) {
@@ -76,6 +77,7 @@
   ThreadTree thread_tree_;
 };
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ThreadTreeTest, maps_smoke) {
   AddMap(0, 5, "0");
   AddMap(10, 15, "1");
@@ -100,6 +102,7 @@
   CheckMaps();
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ThreadTreeTest, jit_maps_before_fork) {
   // Maps for JIT symfiles can arrive before fork records.
   thread_tree_.AddThreadMap(0, 0, 0, 1, 0, "0", map_flags::PROT_JIT_SYMFILE_MAP);
@@ -114,6 +117,7 @@
   ASSERT_EQ(map->flags, map_flags::PROT_JIT_SYMFILE_MAP);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ThreadTreeTest, reused_tid) {
   // Process 1 has thread 1 and 2.
   thread_tree_.ForkThread(1, 2, 1, 1);
@@ -123,12 +127,14 @@
   thread_tree_.ForkThread(2, 2, 1, 1);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ThreadTreeTest, reused_tid_without_thread_exit) {
   // Similar to the above test, but the thread exit record is missing.
   thread_tree_.ForkThread(1, 2, 1, 1);
   thread_tree_.ForkThread(2, 2, 1, 1);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ThreadTreeTest, add_symbols_for_process) {
   std::string symbol_map(
       "0x2000 0x20 two\n"
@@ -144,6 +150,7 @@
   ASSERT_STREQ("three", FindSymbol(1, 1, 0x302f)->Name());
 }
 
+// @CddTest = 6.1/C-0-2
 TEST_F(ThreadTreeTest, invalid_fork) {
   // tid == ptid
   ASSERT_FALSE(thread_tree_.ForkThread(1, 2, 1, 2));
diff --git a/simpleperf/tracing_test.cpp b/simpleperf/tracing_test.cpp
index 4e4558b..f4cec74 100644
--- a/simpleperf/tracing_test.cpp
+++ b/simpleperf/tracing_test.cpp
@@ -32,6 +32,7 @@
   ASSERT_EQ(android::base::Join(used_fields, ","), used_field_str);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(tracing, adjust_tracepoint_filter) {
   std::string filter = "((sig >= 1 && sig < 20) || sig == 32) && comm != \"bash\"";
   CheckAdjustFilter(filter, true, filter, "comm,sig");
@@ -67,6 +68,7 @@
 }
 }  // namespace simpleperf
 
+// @CddTest = 6.1/C-0-2
 TEST(tracing, ParseTracingFormat) {
   std::string data =
       "name: sched_wakeup_new\n"
diff --git a/simpleperf/utils_test.cpp b/simpleperf/utils_test.cpp
index 1560533..747c020 100644
--- a/simpleperf/utils_test.cpp
+++ b/simpleperf/utils_test.cpp
@@ -25,6 +25,7 @@
 
 using namespace simpleperf;
 
+// @CddTest = 6.1/C-0-2
 TEST(utils, ConvertBytesToValue) {
   char buf[8];
   for (int i = 0; i < 8; ++i) {
@@ -36,6 +37,7 @@
   ASSERT_EQ(0x0706050403020100ULL, ConvertBytesToValue(buf, 8));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(utils, ArchiveHelper) {
   std::unique_ptr<ArchiveHelper> ahelper = ArchiveHelper::CreateInstance(GetTestData(APK_FILE));
   ASSERT_TRUE(ahelper);
@@ -61,6 +63,7 @@
   ASSERT_FALSE(ArchiveHelper::CreateInstance("/dev/zero"));
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(utils, GetCpusFromString) {
   ASSERT_EQ(GetCpusFromString("0-2"), std::make_optional<std::set<int>>({0, 1, 2}));
   ASSERT_EQ(GetCpusFromString("0,2-3"), std::make_optional<std::set<int>>({0, 2, 3}));
@@ -72,11 +75,13 @@
   ASSERT_EQ(GetCpusFromString("3,2-1"), std::nullopt);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(utils, GetTidsFromString) {
   ASSERT_EQ(GetTidsFromString("0,12,9", false), std::make_optional(std::set<pid_t>({0, 9, 12})));
   ASSERT_EQ(GetTidsFromString("-2", false), std::nullopt);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(utils, GetPidsFromStrings) {
   ASSERT_EQ(GetPidsFromStrings({"0,12", "9"}, false, false),
             std::make_optional(std::set<pid_t>({0, 9, 12})));
@@ -91,6 +96,7 @@
 #endif  // defined(__linux__)
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(utils, LineReader) {
   TemporaryFile tmpfile;
   close(tmpfile.release());
@@ -106,6 +112,7 @@
   ASSERT_TRUE(reader.ReadLine() == nullptr);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(utils, ReadableCount) {
   ASSERT_EQ(ReadableCount(0), "0");
   ASSERT_EQ(ReadableCount(204), "204");
diff --git a/simpleperf/workload_test.cpp b/simpleperf/workload_test.cpp
index f99ec75..e1ac147 100644
--- a/simpleperf/workload_test.cpp
+++ b/simpleperf/workload_test.cpp
@@ -24,6 +24,7 @@
 
 using namespace simpleperf;
 
+// @CddTest = 6.1/C-0-2
 TEST(workload, success) {
   IOEventLoop loop;
   ASSERT_TRUE(loop.AddSignalEvent(SIGCHLD, [&]() { return loop.ExitLoop(); }));
@@ -34,6 +35,7 @@
   ASSERT_TRUE(loop.RunLoop());
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(workload, execvp_failure) {
   auto workload = Workload::CreateWorkload({"/dev/null"});
   ASSERT_TRUE(workload != nullptr);
@@ -54,6 +56,7 @@
   exit(0);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(workload, signaled_warning) {
   ASSERT_EXIT(run_signaled_workload(), testing::ExitedWithCode(0),
               "child process was terminated by signal");
@@ -72,6 +75,7 @@
   exit(0);
 }
 
+// @CddTest = 6.1/C-0-2
 TEST(workload, exit_nonzero_warning) {
   ASSERT_EXIT(run_exit_nonzero_workload(), testing::ExitedWithCode(0),
               "child process exited with exit code");