Merge "mke2fs.conf: Don't include resize_inode by default."
diff --git a/libfscrypt/fscrypt.cpp b/libfscrypt/fscrypt.cpp
index a1f1fc4..9ea8cd3 100644
--- a/libfscrypt/fscrypt.cpp
+++ b/libfscrypt/fscrypt.cpp
@@ -131,6 +131,12 @@
     return ioctl(fd, FS_IOC_GET_ENCRYPTION_POLICY, &policy) == 0 || errno == EINVAL;
 }
 
+bool operator!=(const EncryptionOptions& lhs, const EncryptionOptions& rhs) {
+    return !((lhs.version == rhs.version) && (lhs.contents_mode == rhs.contents_mode) &&
+             (lhs.filenames_mode == rhs.filenames_mode) && (lhs.flags == rhs.flags) &&
+             (lhs.use_hw_wrapped_key == rhs.use_hw_wrapped_key));
+}
+
 bool OptionsToString(const EncryptionOptions& options, std::string* options_string) {
     std::string contents_mode, filenames_mode;
     if (!LookupModeById(contents_modes, options.contents_mode, &contents_mode)) {
@@ -143,12 +149,15 @@
     if ((options.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64)) {
         *options_string += "+inlinecrypt_optimized";
     }
+    if (options.use_hw_wrapped_key) {
+        *options_string += "+wrappedkey_v0";
+    }
     EncryptionOptions options_check;
     if (!ParseOptions(*options_string, &options_check)) {
         LOG(ERROR) << "Internal error serializing options as string: " << *options_string;
         return false;
     }
-    if (memcmp(&options, &options_check, sizeof(options_check)) != 0) {
+    if (options != options_check) {
         LOG(ERROR) << "Internal error serializing options as string, round trip failed: "
                    << *options_string;
         return false;
@@ -187,6 +196,8 @@
                 options->version = 2;
             } else if (flag == "inlinecrypt_optimized") {
                 options->flags |= FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64;
+            } else if (flag == "wrappedkey_v0") {
+                options->use_hw_wrapped_key = true;
             } else {
                 LOG(ERROR) << "Unknown flag: " << flag;
                 return false;
diff --git a/libfscrypt/include/fscrypt/fscrypt.h b/libfscrypt/include/fscrypt/fscrypt.h
index ca051f4..18fb4fc 100644
--- a/libfscrypt/include/fscrypt/fscrypt.h
+++ b/libfscrypt/include/fscrypt/fscrypt.h
@@ -34,6 +34,7 @@
     int contents_mode;
     int filenames_mode;
     int flags;
+    bool use_hw_wrapped_key;
 
     // Ensure that "version" is not valid on creation and so must be explicitly set
     EncryptionOptions() : version(0) {}
diff --git a/memory_replay/NativeInfo.cpp b/memory_replay/NativeInfo.cpp
index ec131dd..3439a29 100644
--- a/memory_replay/NativeInfo.cpp
+++ b/memory_replay/NativeInfo.cpp
@@ -76,7 +76,8 @@
                  &name_pos) == 2) {
         char* map_name = &buf[buf_start + name_pos];
         if (strcmp(map_name, "[anon:libc_malloc]") == 0 || strcmp(map_name, "[heap]") == 0 ||
-            strncmp(map_name, "[anon:scudo:", 12) == 0) {
+            strncmp(map_name, "[anon:scudo:", 12) == 0 ||
+            strncmp(map_name, "[anon:GWP-ASan", 14) == 0) {
           total_va_bytes += end - start;
           native_map = true;
         } else {
diff --git a/memory_replay/tests/NativeInfoTest.cpp b/memory_replay/tests/NativeInfoTest.cpp
index 845ec04..5c33eb7 100644
--- a/memory_replay/tests/NativeInfoTest.cpp
+++ b/memory_replay/tests/NativeInfoTest.cpp
@@ -269,7 +269,55 @@
       "KernelPageSize:        4 kB\n"
       "MMUPageSize:           4 kB\n"
       "Locked:                0 kB\n"
-      "Name:           [anon:scudo:test]\n";
+      "Name:           [anon:scudo:test]\n"
+      "b8f4c000-b8f4d000 rw-p 00000000 00:00 0          [anon:GWP-ASan Guard Page]\n"
+      "Size:                  4 kB\n"
+      "Rss:                   0 kB\n"
+      "Pss:                   0 kB\n"
+      "Shared_Clean:          0 kB\n"
+      "Shared_Dirty:          0 kB\n"
+      "Private_Clean:         0 kB\n"
+      "Private_Dirty:         0 kB\n"
+      "Referenced:            0 kB\n"
+      "Anonymous:             0 kB\n"
+      "AnonHugePages:         0 kB\n"
+      "Swap:                  0 kB\n"
+      "KernelPageSize:        4 kB\n"
+      "MMUPageSize:           4 kB\n"
+      "Locked:                0 kB\n"
+      "Name:           [anon:GWP-ASan Guard Page]\n"
+      "b8f4d000-b8f4e000 rw-p 00000000 00:00 0          [anon:GWP-ASan Alive Slot]\n"
+      "Size:                  4 kB\n"
+      "Rss:                   4 kB\n"
+      "Pss:                   0 kB\n"
+      "Shared_Clean:          0 kB\n"
+      "Shared_Dirty:          0 kB\n"
+      "Private_Clean:         0 kB\n"
+      "Private_Dirty:         0 kB\n"
+      "Referenced:            0 kB\n"
+      "Anonymous:             0 kB\n"
+      "AnonHugePages:         0 kB\n"
+      "Swap:                  0 kB\n"
+      "KernelPageSize:        4 kB\n"
+      "MMUPageSize:           4 kB\n"
+      "Locked:                0 kB\n"
+      "Name:           [anon:GWP-ASan Alive Slot]\n"
+      "b8f4e000-b8f4f000 rw-p 00000000 00:00 0          [anon:GWP-ASan Guard Page]\n"
+      "Size:                  4 kB\n"
+      "Rss:                   0 kB\n"
+      "Pss:                   0 kB\n"
+      "Shared_Clean:          0 kB\n"
+      "Shared_Dirty:          0 kB\n"
+      "Private_Clean:         0 kB\n"
+      "Private_Dirty:         0 kB\n"
+      "Referenced:            0 kB\n"
+      "Anonymous:             0 kB\n"
+      "AnonHugePages:         0 kB\n"
+      "Swap:                  0 kB\n"
+      "KernelPageSize:        4 kB\n"
+      "MMUPageSize:           4 kB\n"
+      "Locked:                0 kB\n"
+      "Name:           [anon:GWP-ASan Guard Page]\n";
 
   ASSERT_TRUE(TEMP_FAILURE_RETRY(
       write(tmp_file_->fd, smaps_data.c_str(), smaps_data.size())) != -1);
@@ -278,6 +326,6 @@
   size_t rss_bytes = 1;
   size_t va_bytes = 1;
   NativeGetInfo(tmp_file_->fd, &rss_bytes, &va_bytes);
-  EXPECT_EQ(126976U, rss_bytes);
-  EXPECT_EQ(147456U, va_bytes);
+  EXPECT_EQ(131072U, rss_bytes);
+  EXPECT_EQ(159744U, va_bytes);
 }
diff --git a/simpleperf/Android.bp b/simpleperf/Android.bp
index b8b59c0..089a71a 100644
--- a/simpleperf/Android.bp
+++ b/simpleperf/Android.bp
@@ -528,6 +528,7 @@
         linux: {
             srcs: [
                 "CallChainJoiner_test.cpp",
+                "cmd_api_test.cpp",
                 "cmd_debug_unwind_test.cpp",
                 "cmd_dumprecord_test.cpp",
                 "cmd_list_test.cpp",
diff --git a/simpleperf/app_api/cpp/simpleperf.cpp b/simpleperf/app_api/cpp/simpleperf.cpp
index 54b331a..71216fa 100644
--- a/simpleperf/app_api/cpp/simpleperf.cpp
+++ b/simpleperf/app_api/cpp/simpleperf.cpp
@@ -359,8 +359,14 @@
   if (!RunCmd({"/system/bin/cp", path.c_str(), to_path.c_str()}, nullptr)) {
     return "";
   }
-  // For apps with target sdk >= 29, executing app data file isn't allowed. So test executing it.
-  if (!RunCmd({to_path.c_str()}, nullptr)) {
+  // For apps with target sdk >= 29, executing app data file isn't allowed.
+  // For android R, app context isn't allowed to use perf_event_open.
+  // So test executing downloaded simpleperf.
+  std::string s;
+  if (!RunCmd({to_path.c_str(), "list", "sw"}, &s)) {
+    return "";
+  }
+  if (s.find("cpu-clock") == std::string::npos) {
     return "";
   }
   return to_path;
diff --git a/simpleperf/app_api/java/com/android/simpleperf/ProfileSession.java b/simpleperf/app_api/java/com/android/simpleperf/ProfileSession.java
index cb0eac3..1c512c6 100644
--- a/simpleperf/app_api/java/com/android/simpleperf/ProfileSession.java
+++ b/simpleperf/app_api/java/com/android/simpleperf/ProfileSession.java
@@ -248,12 +248,16 @@
         if (!isExecutableFile(toPath)) {
             return null;
         }
-        // For apps with target sdk >= 29, executing app data file isn't allowed. So test executing
-        // it.
+        // For apps with target sdk >= 29, executing app data file isn't allowed.
+        // For android R, app context isn't allowed to use perf_event_open.
+        // So test executing downloaded simpleperf.
         try {
-            Process process = new ProcessBuilder()
-                    .command(toPath).start();
+            Process process = new ProcessBuilder().command(toPath + "list sw").start();
             process.waitFor();
+            String data = readInputStream(process.getInputStream());
+            if (data.indexOf("cpu-clock") == -1) {
+                return null;
+            }
         } catch (Exception e) {
             return null;
         }
diff --git a/simpleperf/cmd_api_test.cpp b/simpleperf/cmd_api_test.cpp
new file mode 100644
index 0000000..6b618e0
--- /dev/null
+++ b/simpleperf/cmd_api_test.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <stdio.h>
+
+#include "command.h"
+#include "get_test_data.h"
+#include "record_file.h"
+#include "test_util.h"
+#include "utils.h"
+
+#if defined(__ANDROID__)
+
+static bool WaitUntilAppExit(const std::string& package_name) {
+  while (true) {
+    std::unique_ptr<FILE, decltype(&pclose)> fp(popen("ps -e", "re"), pclose);
+    if (!fp) {
+      return false;
+    }
+    std::string s;
+    if (!android::base::ReadFdToString(fileno(fp.get()), &s)) {
+      return false;
+    }
+    if (s.find(package_name) == std::string::npos) {
+      break;
+    }
+    sleep(1);
+  }
+  return true;
+}
+
+static void CheckPerfDataFile(const std::string& filename) {
+  auto reader = RecordFileReader::CreateInstance(filename);
+  ASSERT_TRUE(reader);
+  bool has_sample = false;
+  ASSERT_TRUE(reader->ReadDataSection([&](std::unique_ptr<Record> r) {
+    if (r->type() == PERF_RECORD_SAMPLE) {
+      has_sample = true;
+    }
+    return true;
+  }));
+  ASSERT_TRUE(has_sample);
+}
+
+static void RecordApp(const std::string& package_name, const std::string& apk_path) {
+  // 1. Prepare recording.
+  ASSERT_TRUE(CreateCommandInstance("api-prepare")->Run({}));
+
+  // 2. Install apk and start the app.
+  AppHelper app_helper;
+  ASSERT_TRUE(app_helper.InstallApk(apk_path, package_name));
+  ASSERT_TRUE(app_helper.StartApp("am start " + package_name + "/.MainActivity"));
+
+  // 3. Wait until the app stops.
+  sleep(3);
+  ASSERT_TRUE(WaitUntilAppExit(package_name));
+
+  // 4. Collect perf.data.
+  TemporaryFile tmpfile;
+  ASSERT_TRUE(
+      CreateCommandInstance("api-collect")->Run({"--app", package_name, "-o", tmpfile.path}));
+
+  // 5. Verify perf.data.
+  TemporaryDir tmpdir;
+  ASSERT_TRUE(Workload::RunCmd({"unzip", "-d", tmpdir.path, tmpfile.path}));
+  for (const std::string& filename : GetEntriesInDir(tmpdir.path)) {
+    CheckPerfDataFile(std::string(tmpdir.path) + "/" + filename);
+  }
+}
+
+#endif  // defined(__ANDROID__)
+
+TEST(cmd_api, java_app) {
+#if defined(__ANDROID__)
+  RecordApp("simpleperf.demo.java_api", GetTestData("java_api.apk"));
+#else
+  GTEST_LOG_(INFO) << "This test tests recording apps on Android.";
+#endif
+}
+
+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_record_test.cpp b/simpleperf/cmd_record_test.cpp
index f4ed1d8..82f48ed 100644
--- a/simpleperf/cmd_record_test.cpp
+++ b/simpleperf/cmd_record_test.cpp
@@ -769,16 +769,11 @@
 class RecordingAppHelper {
  public:
   bool InstallApk(const std::string& apk_path, const std::string& package_name) {
-    if (Workload::RunCmd({"pm", "install", "-t", "--abi", GetABI(), apk_path})) {
-      installed_packages_.emplace_back(package_name);
-      return true;
-    }
-    return false;
+    return app_helper_.InstallApk(apk_path, package_name);
   }
 
   bool StartApp(const std::string& start_cmd) {
-    app_start_proc_ = Workload::CreateWorkload(android::base::Split(start_cmd, " "));
-    return app_start_proc_ && app_start_proc_->Start();
+    return app_helper_.StartApp(start_cmd);
   }
 
   bool RecordData(const std::string& record_cmd) {
@@ -800,29 +795,8 @@
     return success;
   }
 
-  ~RecordingAppHelper() {
-    for (auto& package : installed_packages_) {
-      Workload::RunCmd({"pm", "uninstall", package});
-    }
-  }
-
  private:
-  const char* GetABI() {
-#if defined(__i386__)
-    return "x86";
-#elif defined(__x86_64__)
-    return "x86_64";
-#elif defined(__aarch64__)
-    return "arm64-v8a";
-#elif defined(__arm__)
-    return "armeabi-v7a";
-#else
-    #error "unrecognized ABI"
-#endif
-  }
-
-  std::vector<std::string> installed_packages_;
-  std::unique_ptr<Workload> app_start_proc_;
+  AppHelper app_helper_;
   TemporaryFile perf_data_file_;
 };
 
diff --git a/simpleperf/demo/CppApi/app/src/main/cpp/native-lib.cpp b/simpleperf/demo/CppApi/app/src/main/cpp/native-lib.cpp
index bdf5f46..34b8078 100644
--- a/simpleperf/demo/CppApi/app/src/main/cpp/native-lib.cpp
+++ b/simpleperf/demo/CppApi/app/src/main/cpp/native-lib.cpp
@@ -32,11 +32,11 @@
 void* ProfileThreadFunc(void*) {
   pthread_setname_np(pthread_self(), "ProfileThread");
   simpleperf::RecordOptions options;
-  options.RecordDwarfCallGraph();
+  options.RecordDwarfCallGraph().SetEvent("cpu-clock");
   simpleperf::ProfileSession session;
   log("start recording");
   session.StartRecording(options);
-  for (int i = 0; i < 3; i++) {
+  for (int i = 0; i < 1; i++) {
     sleep(1);
     log("pause recording");
     session.PauseRecording();
@@ -72,6 +72,8 @@
     nanosleep(&ts, nullptr);
     count++;
   }
+  // Exit after recording. So we can build test apk, and expect profiling data file after app exits.
+  exit(0);
   return nullptr;
 }
 
diff --git a/simpleperf/demo/JavaApi/app/src/main/java/simpleperf/demo/java_api/MainActivity.java b/simpleperf/demo/JavaApi/app/src/main/java/simpleperf/demo/java_api/MainActivity.java
index 9cb0c4a..696689f 100644
--- a/simpleperf/demo/JavaApi/app/src/main/java/simpleperf/demo/java_api/MainActivity.java
+++ b/simpleperf/demo/JavaApi/app/src/main/java/simpleperf/demo/java_api/MainActivity.java
@@ -49,12 +49,12 @@
             @Override
             public void run() {
                 RecordOptions recordOptions = new RecordOptions();
-                recordOptions.recordDwarfCallGraph().setDuration(100);
+                recordOptions.recordDwarfCallGraph().setDuration(100).setEvent("cpu-clock");
                 ProfileSession profileSession = new ProfileSession();
                 try {
                     Log.e("simpleperf", "startRecording");
                     profileSession.startRecording(recordOptions);
-                    for (int i = 0; i < 3; i++) {
+                    for (int i = 0; i < 1; i++) {
                         Thread.sleep(1000);
                         Log.e("simpleperf", "pauseRecording");
                         profileSession.pauseRecording();
@@ -99,6 +99,9 @@
                         }
                     });
                 }
+                // Exit after recording. So we can build test apk, and expect profiling data file
+                // after app exits.
+                System.exit(0);
             }
 
             private int callFunction(int a) {
diff --git a/simpleperf/test_util.h b/simpleperf/test_util.h
index 90ab719..5780b6c 100644
--- a/simpleperf/test_util.h
+++ b/simpleperf/test_util.h
@@ -20,6 +20,7 @@
 #include <vector>
 
 #include <android-base/file.h>
+#include <android-base/strings.h>
 
 #include "environment.h"
 #include "read_elf.h"
@@ -138,3 +139,43 @@
   int old_stdout_;
   std::unique_ptr<TemporaryFile> tmpfile_;
 };
+
+class AppHelper {
+ public:
+  ~AppHelper() {
+    for (auto& package : installed_packages_) {
+      Workload::RunCmd({"pm", "uninstall", package});
+    }
+  }
+
+  bool InstallApk(const std::string& apk_path, const std::string& package_name) {
+    if (Workload::RunCmd({"pm", "install", "-t", "--abi", GetABI(), apk_path})) {
+      installed_packages_.emplace_back(package_name);
+      return true;
+    }
+    return false;
+  }
+
+  bool StartApp(const std::string& start_cmd) {
+    app_start_proc_ = Workload::CreateWorkload(android::base::Split(start_cmd, " "));
+    return app_start_proc_ && app_start_proc_->Start();
+  }
+
+ private:
+  const char* GetABI() {
+#if defined(__i386__)
+    return "x86";
+#elif defined(__x86_64__)
+    return "x86_64";
+#elif defined(__aarch64__)
+    return "arm64-v8a";
+#elif defined(__arm__)
+    return "armeabi-v7a";
+#else
+    #error "unrecognized ABI"
+#endif
+  }
+
+  std::vector<std::string> installed_packages_;
+  std::unique_ptr<Workload> app_start_proc_;
+};
\ No newline at end of file
diff --git a/simpleperf/testdata/cpp_api.apk b/simpleperf/testdata/cpp_api.apk
new file mode 100644
index 0000000..5add50d
--- /dev/null
+++ b/simpleperf/testdata/cpp_api.apk
Binary files differ
diff --git a/simpleperf/testdata/java_api.apk b/simpleperf/testdata/java_api.apk
new file mode 100644
index 0000000..a2dbb5d
--- /dev/null
+++ b/simpleperf/testdata/java_api.apk
Binary files differ