Merge "Use getCapabilities call to ping vibrator AIDL HAL"
diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp
index 4058934..1f055f3 100644
--- a/cmds/dumpstate/Android.bp
+++ b/cmds/dumpstate/Android.bp
@@ -105,6 +105,7 @@
     name: "dumpstate",
     defaults: ["dumpstate_defaults"],
     srcs: [
+        "DumpPool.cpp",
         "dumpstate.cpp",
         "main.cpp",
     ],
@@ -132,6 +133,7 @@
     name: "dumpstate_test",
     defaults: ["dumpstate_defaults"],
     srcs: [
+        "DumpPool.cpp",
         "dumpstate.cpp",
         "tests/dumpstate_test.cpp",
     ],
@@ -148,6 +150,7 @@
     name: "dumpstate_smoke_test",
     defaults: ["dumpstate_defaults"],
     srcs: [
+        "DumpPool.cpp",
         "dumpstate.cpp",
         "tests/dumpstate_smoke_test.cpp",
     ],
diff --git a/cmds/dumpstate/DumpPool.cpp b/cmds/dumpstate/DumpPool.cpp
new file mode 100644
index 0000000..7324ead
--- /dev/null
+++ b/cmds/dumpstate/DumpPool.cpp
@@ -0,0 +1,171 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "dumpstate"
+
+#include "DumpPool.h"
+
+#include <array>
+#include <thread>
+
+#include <log/log.h>
+
+#include "dumpstate.h"
+#include "DumpstateInternal.h"
+#include "DumpstateUtil.h"
+
+namespace android {
+namespace os {
+namespace dumpstate {
+
+const std::string DumpPool::PREFIX_TMPFILE_NAME = "dump-tmp.";
+
+DumpPool::DumpPool(const std::string& tmp_root) : tmp_root_(tmp_root), shutdown_(false) {
+    assert(!tmp_root.empty());
+    deleteTempFiles(tmp_root_);
+}
+
+DumpPool::~DumpPool() {
+    shutdown();
+}
+
+void DumpPool::start(int thread_counts) {
+    assert(thread_counts > 0);
+    assert(threads_.empty());
+    if (thread_counts > MAX_THREAD_COUNT) {
+        thread_counts = MAX_THREAD_COUNT;
+    }
+    MYLOGI("Start thread pool:%d", thread_counts);
+    shutdown_ = false;
+    for (int i = 0; i < thread_counts; i++) {
+        threads_.emplace_back(std::thread([=]() {
+            setThreadName(pthread_self(), i + 1);
+            loop();
+        }));
+    }
+}
+
+void DumpPool::shutdown() {
+    std::unique_lock lock(lock_);
+    if (shutdown_ || threads_.empty()) {
+        return;
+    }
+    while (!tasks_.empty()) tasks_.pop();
+    futures_map_.clear();
+
+    shutdown_ = true;
+    condition_variable_.notify_all();
+    lock.unlock();
+
+    for (auto& thread : threads_) {
+        thread.join();
+    }
+    threads_.clear();
+    deleteTempFiles(tmp_root_);
+    MYLOGI("shutdown thread pool");
+}
+
+void DumpPool::waitForTask(const std::string& task_name, const std::string& title,
+        int out_fd) {
+    DurationReporter duration_reporter("Wait for " + task_name, true);
+    auto iterator = futures_map_.find(task_name);
+    if (iterator == futures_map_.end()) {
+        MYLOGW("Task %s does not exist", task_name.c_str());
+        return;
+    }
+    Future future = iterator->second;
+    futures_map_.erase(iterator);
+
+    std::string result = future.get();
+    if (result.empty()) {
+        return;
+    }
+    DumpFileToFd(out_fd, title, result);
+    if (unlink(result.c_str())) {
+        MYLOGE("Failed to unlink (%s): %s\n", result.c_str(), strerror(errno));
+    }
+}
+
+std::unique_ptr<DumpPool::TmpFile> DumpPool::createTempFile() {
+    auto tmp_file_ptr = std::make_unique<TmpFile>();
+    std::string file_name_format = "%s/" + PREFIX_TMPFILE_NAME + "XXXXXX";
+    snprintf(tmp_file_ptr->path, sizeof(tmp_file_ptr->path), file_name_format.c_str(),
+             tmp_root_.c_str());
+    tmp_file_ptr->fd.reset(TEMP_FAILURE_RETRY(
+            mkostemp(tmp_file_ptr->path, O_CLOEXEC)));
+    if (tmp_file_ptr->fd.get() == -1) {
+        MYLOGE("open(%s, %s)\n", tmp_file_ptr->path, strerror(errno));
+        tmp_file_ptr = nullptr;
+        return tmp_file_ptr;
+    }
+    return tmp_file_ptr;
+}
+
+void DumpPool::deleteTempFiles(const std::string& folder) {
+    std::unique_ptr<DIR, decltype(&closedir)> dir_ptr(opendir(folder.c_str()),
+            &closedir);
+    if (!dir_ptr) {
+        MYLOGE("Failed to opendir (%s): %s\n", folder.c_str(), strerror(errno));
+        return;
+    }
+    int dir_fd = dirfd(dir_ptr.get());
+    if (dir_fd < 0) {
+        MYLOGE("Failed to get fd of dir (%s): %s\n", folder.c_str(),
+               strerror(errno));
+        return;
+    }
+
+    struct dirent* de;
+    while ((de = readdir(dir_ptr.get()))) {
+        if (de->d_type != DT_REG) {
+            continue;
+        }
+        std::string file_name(de->d_name);
+        if (file_name.find(PREFIX_TMPFILE_NAME) != 0) {
+            continue;
+        }
+        if (unlinkat(dir_fd, file_name.c_str(), 0)) {
+            MYLOGE("Failed to unlink (%s): %s\n", file_name.c_str(),
+                   strerror(errno));
+        }
+    }
+}
+
+void DumpPool::setThreadName(const pthread_t thread, int id) {
+    std::array<char, 15> name;
+    snprintf(name.data(), name.size(), "dumpstate_%d", id);
+    pthread_setname_np(thread, name.data());
+}
+
+void DumpPool::loop() {
+    std::unique_lock lock(lock_);
+    while (!shutdown_) {
+        if (tasks_.empty()) {
+            condition_variable_.wait(lock);
+            continue;
+        } else {
+            std::packaged_task<std::string()> task = std::move(tasks_.front());
+            tasks_.pop();
+            lock.unlock();
+            std::invoke(task);
+            lock.lock();
+        }
+    }
+}
+
+}  // namespace dumpstate
+}  // namespace os
+}  // namespace android
diff --git a/cmds/dumpstate/DumpPool.h b/cmds/dumpstate/DumpPool.h
new file mode 100644
index 0000000..266d519
--- /dev/null
+++ b/cmds/dumpstate/DumpPool.h
@@ -0,0 +1,161 @@
+/*
+ * 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.
+ */
+
+#ifndef FRAMEWORK_NATIVE_CMD_DUMPPOOL_H_
+#define FRAMEWORK_NATIVE_CMD_DUMPPOOL_H_
+
+#include <future>
+#include <map>
+#include <queue>
+#include <string>
+
+#include <android-base/file.h>
+#include <android-base/macros.h>
+
+namespace android {
+namespace os {
+namespace dumpstate {
+
+/*
+ * A thread pool with the fixed number of threads to execute multiple dump tasks
+ * simultaneously for the dumpstate. The dump task is a callable function
+ * included a file descriptor as a parameter, and the task could dump results to
+ * that fd. For example:
+ *
+ * void DumpXXXX(int out_fd) {
+ *     dprintf(out_fd, "Dump result to out_fd ...");
+ * }
+ * ...
+ * DumpPool pool(tmp_root);
+ * pool.enqueueTask("TaskName", &DumpXXXX, std::placeholders::_1);
+ * ...
+ * pool.waitForTask("TaskName");
+ *
+ * DumpXXXX is a callable function included a out_fd parameter. Using the
+ * enqueueTask method in DumpPool to enqueue the task to the pool. The
+ * std::placeholders::_1 is placeholder for DumpPool to pass a fd argument.
+ */
+class DumpPool {
+  public:
+    /*
+     * Creates a thread pool.
+     *
+     * |tmp_root| A path to a temporary folder for threads to create temporary
+     * files.
+     */
+    explicit DumpPool(const std::string& tmp_root);
+    ~DumpPool();
+
+    /*
+     * Starts the threads in the pool.
+     *
+     * |thread_counts| the number of threads to start.
+     */
+    void start(int thread_counts = MAX_THREAD_COUNT);
+
+    /*
+     * Requests to shutdown the pool and waits until all threads exit the loop.
+     */
+    void shutdown();
+
+    /*
+     * Adds a task with a task name into the queue of the thread pool.
+     *
+     * |task_name| The name of the task.
+     * |f| Callable function to execute the task. This function must
+     *     include a parameter of file descriptor to output dump result.
+     * |args| A list of arguments.
+     */
+    template<class F, class... Args> void enqueueTask(const std::string& task_name,
+            F&& f, Args&&... args) {
+        auto func = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
+        futures_map_[task_name] = post(func);
+        if (threads_.empty()) {
+            start();
+        }
+    }
+
+    /*
+     * Waits until the task is finished. Dumps the task results to the STDOUT_FILENO.
+     */
+    void waitForTask(const std::string& task_name) {
+        waitForTask(task_name, "", STDOUT_FILENO);
+    }
+
+    /*
+     * Waits until the task is finished. Dumps the task results to the specified
+     * out_fd.
+     *
+     * |task_name| The name of the task.
+     * |title| Dump title string to the out_fd, an empty string for nothing.
+     * |out_fd| The target file to dump the result from the task.
+     */
+    void waitForTask(const std::string& task_name, const std::string& title, int out_fd);
+
+    static const std::string PREFIX_TMPFILE_NAME;
+
+  private:
+    using Task = std::packaged_task<std::string()>;
+    using Future = std::shared_future<std::string>;
+
+    template<class T> Future post(T dump_func) {
+        Task packaged_task([=]() {
+            std::unique_ptr<TmpFile> tmp_file_ptr = createTempFile();
+            if (!tmp_file_ptr) {
+                return std::string("");
+            }
+            std::invoke(dump_func, tmp_file_ptr->fd.get());
+            fsync(tmp_file_ptr->fd.get());
+            return std::string(tmp_file_ptr->path);
+        });
+        std::unique_lock lock(lock_);
+        auto future = packaged_task.get_future().share();
+        tasks_.push(std::move(packaged_task));
+        condition_variable_.notify_one();
+        return future;
+    }
+
+    typedef struct {
+      android::base::unique_fd fd;
+      char path[1024];
+    } TmpFile;
+
+    std::unique_ptr<TmpFile> createTempFile();
+    void deleteTempFiles(const std::string& folder);
+    void setThreadName(const pthread_t thread, int id);
+    void loop();
+
+  private:
+    static const int MAX_THREAD_COUNT = 4;
+
+    /* A path to a temporary folder for threads to create temporary files. */
+    std::string tmp_root_;
+    bool shutdown_;
+    std::mutex lock_;  // A lock for the tasks_.
+    std::condition_variable condition_variable_;
+
+    std::vector<std::thread> threads_;
+    std::queue<Task> tasks_;
+    std::map<std::string, Future> futures_map_;
+
+    DISALLOW_COPY_AND_ASSIGN(DumpPool);
+};
+
+}  // namespace dumpstate
+}  // namespace os
+}  // namespace android
+
+#endif //FRAMEWORK_NATIVE_CMD_DUMPPOOL_H_
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index c7df1bb..d0a4826 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -21,6 +21,7 @@
 #include "DumpstateService.h"
 #include "android/os/BnDumpstate.h"
 #include "dumpstate.h"
+#include "DumpPool.h"
 
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
@@ -46,6 +47,7 @@
 
 using ::android::hardware::dumpstate::V1_1::DumpstateMode;
 using ::testing::EndsWith;
+using ::testing::Eq;
 using ::testing::HasSubstr;
 using ::testing::IsEmpty;
 using ::testing::IsNull;
@@ -1618,6 +1620,80 @@
     EXPECT_THAT(out, EndsWith("skipped on dry run\n"));
 }
 
+class DumpPoolTest : public DumpstateBaseTest {
+  public:
+    void SetUp() {
+        DumpstateBaseTest::SetUp();
+        CreateOutputFile();
+    }
+
+    void CreateOutputFile() {
+        out_path_ = kTestDataPath + "out.txt";
+        out_fd_.reset(TEMP_FAILURE_RETRY(open(out_path_.c_str(),
+                O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
+                S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
+        ASSERT_GE(out_fd_.get(), 0) << "could not create FD for path "
+                << out_path_;
+    }
+
+    int getTempFileCounts(const std::string& folder) {
+        int count = 0;
+        std::unique_ptr<DIR, decltype(&closedir)> dir_ptr(opendir(folder.c_str()),
+                &closedir);
+        if (!dir_ptr) {
+            return -1;
+        }
+        int dir_fd = dirfd(dir_ptr.get());
+        if (dir_fd < 0) {
+            return -1;
+        }
+
+        struct dirent* de;
+        while ((de = readdir(dir_ptr.get()))) {
+            if (de->d_type != DT_REG) {
+                continue;
+            }
+            std::string file_name(de->d_name);
+            if (file_name.find(DumpPool::PREFIX_TMPFILE_NAME) != 0) {
+                continue;
+            }
+            count++;
+        }
+        return count;
+    }
+
+    android::base::unique_fd out_fd_;
+    std::string out_path_;
+};
+
+TEST_F(DumpPoolTest, EnqueueTask) {
+    DumpPool pool(kTestDataPath);
+    auto dump_func_1 = [](int out_fd) {
+        dprintf(out_fd, "A");
+    };
+    auto dump_func_2 = [](int out_fd) {
+        dprintf(out_fd, "B");
+        sleep(1);
+    };
+    auto dump_func_3 = [](int out_fd) {
+        dprintf(out_fd, "C");
+    };
+    pool.enqueueTask(/* task_name = */"1", dump_func_1, std::placeholders::_1);
+    pool.enqueueTask(/* task_name = */"2", dump_func_2, std::placeholders::_1);
+    pool.enqueueTask(/* task_name = */"3", dump_func_3, std::placeholders::_1);
+
+    pool.waitForTask("1", "", out_fd_.get());
+    pool.waitForTask("2", "", out_fd_.get());
+    pool.waitForTask("3", "", out_fd_.get());
+
+    std::string result;
+    ReadFileToString(out_path_, &result);
+    EXPECT_THAT(result, StrEq("A\nB\nC\n"));
+    EXPECT_THAT(getTempFileCounts(kTestDataPath), Eq(0));
+    pool.shutdown();
+}
+
+
 }  // namespace dumpstate
 }  // namespace os
 }  // namespace android
diff --git a/libs/binder/ndk/include_platform/android/binder_manager.h b/libs/binder/ndk/include_platform/android/binder_manager.h
index 055c79b..52bcd20 100644
--- a/libs/binder/ndk/include_platform/android/binder_manager.h
+++ b/libs/binder/ndk/include_platform/android/binder_manager.h
@@ -18,6 +18,7 @@
 
 #include <android/binder_ibinder.h>
 #include <android/binder_status.h>
+#include <sys/cdefs.h>
 
 __BEGIN_DECLS
 
@@ -50,4 +51,47 @@
  */
 __attribute__((warn_unused_result)) AIBinder* AServiceManager_getService(const char* instance);
 
+/**
+ * Registers a lazy service with the default service manager under the 'instance' name.
+ * Does not take ownership of binder.
+ * The service must be configured statically with init so it can be restarted with
+ * ctl.interface.* messages from servicemanager.
+ * AServiceManager_registerLazyService cannot safely be used with AServiceManager_addService
+ * in the same process. If one service is registered with AServiceManager_registerLazyService,
+ * the entire process will have its lifetime controlled by servicemanager.
+ * Instead, all services in the process should be registered using
+ * AServiceManager_registerLazyService.
+ *
+ * \param binder object to register globally with the service manager.
+ * \param instance identifier of the service. This will be used to lookup the service.
+ *
+ * \return STATUS_OK on success.
+ */
+binder_status_t AServiceManager_registerLazyService(AIBinder* binder, const char* instance)
+        __INTRODUCED_IN(31);
+
+/**
+ * Gets a binder object with this specific instance name. Efficiently waits for the service.
+ * If the service is not declared, it will wait indefinitely. Requires the threadpool
+ * to be started in the service.
+ * This also implicitly calls AIBinder_incStrong (so the caller of this function is responsible
+ * for calling AIBinder_decStrong).
+ *
+ * \param instance identifier of the service used to lookup the service.
+ *
+ * \return service if registered, null if not.
+ */
+__attribute__((warn_unused_result)) AIBinder* AServiceManager_waitForService(const char* instance)
+        __INTRODUCED_IN(31);
+
+/**
+ * Check if a service is declared (e.g. VINTF manifest).
+ *
+ * \param instance identifier of the service.
+ *
+ * \return true on success, meaning AServiceManager_waitForService should always
+ *    be able to return the service.
+ */
+bool AServiceManager_isDeclared(const char* instance) __INTRODUCED_IN(31);
+
 __END_DECLS
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index d435382..1701fb5 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -117,6 +117,9 @@
     ABinderProcess_setupPolling; # apex
     AIBinder_getCallingSid; # apex
     AIBinder_setRequestingSid; # apex
+    AServiceManager_isDeclared; # apex llndk
+    AServiceManager_registerLazyService; # llndk
+    AServiceManager_waitForService; # apex llndk
 };
 
 LIBBINDER_NDK_PLATFORM {
diff --git a/libs/binder/ndk/service_manager.cpp b/libs/binder/ndk/service_manager.cpp
index d0b166d..6b2184e 100644
--- a/libs/binder/ndk/service_manager.cpp
+++ b/libs/binder/ndk/service_manager.cpp
@@ -20,6 +20,7 @@
 #include "status_internal.h"
 
 #include <binder/IServiceManager.h>
+#include <binder/LazyServiceRegistrar.h>
 
 using ::android::defaultServiceManager;
 using ::android::IBinder;
@@ -61,3 +62,33 @@
     AIBinder_incStrong(ret.get());
     return ret.get();
 }
+binder_status_t AServiceManager_registerLazyService(AIBinder* binder, const char* instance) {
+    if (binder == nullptr || instance == nullptr) {
+        return STATUS_UNEXPECTED_NULL;
+    }
+
+    auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance();
+    status_t status = serviceRegistrar.registerService(binder->getBinder(), instance);
+
+    return PruneStatusT(status);
+}
+AIBinder* AServiceManager_waitForService(const char* instance) {
+    if (instance == nullptr) {
+        return nullptr;
+    }
+
+    sp<IServiceManager> sm = defaultServiceManager();
+    sp<IBinder> binder = sm->waitForService(String16(instance));
+
+    sp<AIBinder> ret = ABpBinder::lookupOrCreateFromBinder(binder);
+    AIBinder_incStrong(ret.get());
+    return ret.get();
+}
+bool AServiceManager_isDeclared(const char* instance) {
+    if (instance == nullptr) {
+        return false;
+    }
+
+    sp<IServiceManager> sm = defaultServiceManager();
+    return sm->isDeclared(String16(instance));
+}
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index 9b2fcf0..332b4ca 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -43,6 +43,7 @@
 
 constexpr char kExistingNonNdkService[] = "SurfaceFlinger";
 constexpr char kBinderNdkUnitTestService[] = "BinderNdkUnitTest";
+constexpr char kLazyBinderNdkUnitTestService[] = "LazyBinderNdkUnitTest";
 
 class MyBinderNdkUnitTest : public aidl::BnBinderNdkUnitTest {
     ndk::ScopedAStatus repeatInt(int32_t in, int32_t* out) {
@@ -143,6 +144,27 @@
     return 1;
 }
 
+int lazyService(const char* instance) {
+    ABinderProcess_setThreadPoolMaxThreadCount(0);
+    // Wait to register this service to make sure the main test process will
+    // actually wait for the service to be available. Tested with sleep(60),
+    // and reduced for sake of time.
+    sleep(1);
+    // Strong reference to MyBinderNdkUnitTest kept by service manager.
+    // This is just for testing, it has no corresponding init behavior.
+    auto service = ndk::SharedRefBase::make<MyBinderNdkUnitTest>();
+    auto binder = service->asBinder();
+
+    binder_status_t status = AServiceManager_registerLazyService(binder.get(), instance);
+    if (status != STATUS_OK) {
+        LOG(FATAL) << "Could not register: " << status << " " << instance;
+    }
+
+    ABinderProcess_joinThreadPool();
+
+    return 1;  // should not return
+}
+
 // This is too slow
 // TEST(NdkBinder, GetServiceThatDoesntExist) {
 //     sp<IFoo> foo = IFoo::getService("asdfghkl;");
@@ -171,6 +193,33 @@
     EXPECT_EQ(2, out);
 }
 
+TEST(NdkBinder, GetLazyService) {
+    // Not declared in the vintf manifest
+    ASSERT_FALSE(AServiceManager_isDeclared(kLazyBinderNdkUnitTestService));
+    ndk::SpAIBinder binder(AServiceManager_waitForService(kLazyBinderNdkUnitTestService));
+    std::shared_ptr<aidl::IBinderNdkUnitTest> service =
+            aidl::IBinderNdkUnitTest::fromBinder(binder);
+    ASSERT_NE(service, nullptr);
+
+    EXPECT_EQ(STATUS_OK, AIBinder_ping(binder.get()));
+}
+
+// This is too slow
+TEST(NdkBinder, CheckLazyServiceShutDown) {
+    ndk::SpAIBinder binder(AServiceManager_waitForService(kLazyBinderNdkUnitTestService));
+    std::shared_ptr<aidl::IBinderNdkUnitTest> service =
+            aidl::IBinderNdkUnitTest::fromBinder(binder);
+    ASSERT_NE(service, nullptr);
+
+    EXPECT_EQ(STATUS_OK, AIBinder_ping(binder.get()));
+    binder = nullptr;
+    service = nullptr;
+    IPCThreadState::self()->flushCommands();
+    // Make sure the service is dead after some time of no use
+    sleep(10);
+    ASSERT_EQ(nullptr, AServiceManager_checkService(kLazyBinderNdkUnitTestService));
+}
+
 void LambdaOnDeath(void* cookie) {
     auto onDeath = static_cast<std::function<void(void)>*>(cookie);
     (*onDeath)();
@@ -477,6 +526,10 @@
     }
     if (fork() == 0) {
         prctl(PR_SET_PDEATHSIG, SIGHUP);
+        return lazyService(kLazyBinderNdkUnitTestService);
+    }
+    if (fork() == 0) {
+        prctl(PR_SET_PDEATHSIG, SIGHUP);
         return generatedService();
     }
 
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index de3a9a7..5e1066b 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -339,7 +339,7 @@
 struct LayerCaptureArgs : CaptureArgs {
     sp<IBinder> layerHandle;
     std::unordered_set<sp<IBinder>, ISurfaceComposer::SpHash<IBinder>> excludeHandles;
-    bool childrenOnly{true};
+    bool childrenOnly{false};
 
     status_t write(Parcel& output) const override;
     status_t read(const Parcel& input) override;
diff --git a/services/gpuservice/tracing/GpuMemTracer.cpp b/services/gpuservice/tracing/GpuMemTracer.cpp
index c9bfa57..9e01a64 100644
--- a/services/gpuservice/tracing/GpuMemTracer.cpp
+++ b/services/gpuservice/tracing/GpuMemTracer.cpp
@@ -44,10 +44,6 @@
     mGpuMem = gpuMem;
     perfetto::TracingInitArgs args;
     args.backends = perfetto::kSystemBackend;
-    // TODO(b/160016498): Find a better way to wait for traced
-    // Sleep for 30 seconds to make sure the data source is registered only
-    // after traced starts.
-    sleep(30);
     perfetto::Tracing::Initialize(args);
     registerDataSource();
     std::thread tracerThread(&GpuMemTracer::threadLoop, this);
diff --git a/services/inputflinger/VibrationElement.cpp b/services/inputflinger/VibrationElement.cpp
index a69f5d0..aaf5834 100644
--- a/services/inputflinger/VibrationElement.cpp
+++ b/services/inputflinger/VibrationElement.cpp
@@ -25,38 +25,27 @@
 
 namespace android {
 
-// The sentinel to use the default amplitude
-static const int DEFAULT_AMPLITUDE = -1;
-
-// The vibration magnitude for the "DEFAULT_AMPLITUDE" magnitude constant.
-static const uint16_t DEFAULT_MAGNITUDE = 0xc000;
-
-void VibrationElement::dump(std::string& dump) const {
+const std::string VibrationElement::toString() const {
+    std::string dump;
     dump += StringPrintf("[duration=%lldms, channels=[", duration.count());
 
-    if (channels.size()) {
-        dump += std::to_string(channels[0]);
-        std::for_each(channels.begin() + 1, channels.end(), [&dump](int channel) {
+    for (auto it = channels.begin(); it != channels.end(); ++it) {
+        dump += std::to_string(*it);
+        if (std::next(it) != channels.end()) {
             dump += ", ";
-            dump += std::to_string(channel);
-        });
+        }
     }
+
     dump += "]]";
+    return dump;
 }
 
-uint16_t VibrationElement::getChannel(int id) const {
-    if (id >= (int)channels.size()) {
+uint16_t VibrationElement::getMagnitude(size_t channelIdx) const {
+    if (channelIdx >= channels.size()) {
         return 0;
     }
-
-    // android framework uses DEFAULT_AMPLITUDE to signal that the vibration
-    // should use some built-in default value, denoted here as DEFAULT_MAGNITUDE
-    if (channels[id] == DEFAULT_AMPLITUDE) {
-        return DEFAULT_MAGNITUDE;
-    }
-
     // convert range [0,255] to [0,65535] (android framework to linux ff ranges)
-    return ((uint16_t)channels[id]) << 8;
+    return static_cast<uint16_t>(channels[channelIdx]) << 8;
 }
 
 bool VibrationElement::isOn() const {
diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h
index 5a832e7..a24b293 100644
--- a/services/inputflinger/include/InputReaderBase.h
+++ b/services/inputflinger/include/InputReaderBase.h
@@ -39,11 +39,6 @@
 // Must be at least 2.
 #define MAX_VIBRATE_PATTERN_SIZE 100
 
-// Maximum allowable delay value in a vibration pattern before
-// which the delay will be truncated.
-#define MAX_VIBRATE_PATTERN_DELAY_NSECS (1000000 * 1000000000LL)
-#define MAX_VIBRATE_PATTERN_DELAY_MSECS (1000000 * 1000LL)
-
 namespace android {
 
 // --- InputReaderInterface ---
diff --git a/services/inputflinger/include/VibrationElement.h b/services/inputflinger/include/VibrationElement.h
index 8a134ee..b60ffac 100644
--- a/services/inputflinger/include/VibrationElement.h
+++ b/services/inputflinger/include/VibrationElement.h
@@ -17,22 +17,25 @@
 #ifndef _VIBRATION_ELEMENT_H
 #define _VIBRATION_ELEMENT_H
 
+#include <array>
 #include <chrono>
 #include <cstdint>
 #include <string>
-#include <vector>
 
 namespace android {
 
+// evdev FF_RUMBLE effect only supports two channels of vibration.
+constexpr size_t CHANNEL_SIZE = 2;
 /*
  * Describes a rumble effect
  */
 struct VibrationElement {
     std::chrono::milliseconds duration;
-    std::vector<int> channels;
+    // Channel amplitude range 0-255.
+    std::array<uint8_t, CHANNEL_SIZE> channels = {0, 0};
 
-    void dump(std::string& dump) const;
-    uint16_t getChannel(int id) const;
+    const std::string toString() const;
+    uint16_t getMagnitude(size_t channelIndex) const;
     bool isOn() const;
 };
 
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index 8f34e8a..cde977f 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -61,6 +61,9 @@
 // v4l2 devices go directly into /dev
 static const char* VIDEO_DEVICE_PATH = "/dev";
 
+static constexpr size_t FF_STRONG_MAGNITUDE_CHANNEL_IDX = 0;
+static constexpr size_t FF_WEAK_MAGNITUDE_CHANNEL_IDX = 1;
+
 static inline const char* toString(bool value) {
     return value ? "true" : "false";
 }
@@ -834,8 +837,8 @@
         effect.type = FF_RUMBLE;
         effect.id = device->ffEffectId;
         // evdev FF_RUMBLE effect only supports two channels of vibration.
-        effect.u.rumble.strong_magnitude = element.getChannel(0);
-        effect.u.rumble.weak_magnitude = element.getChannel(1);
+        effect.u.rumble.strong_magnitude = element.getMagnitude(FF_STRONG_MAGNITUDE_CHANNEL_IDX);
+        effect.u.rumble.weak_magnitude = element.getMagnitude(FF_WEAK_MAGNITUDE_CHANNEL_IDX);
         effect.replay.length = element.duration.count();
         effect.replay.delay = 0;
         if (ioctl(device->fd, EVIOCSFF, &effect)) {
diff --git a/services/inputflinger/reader/mapper/VibratorInputMapper.cpp b/services/inputflinger/reader/mapper/VibratorInputMapper.cpp
index 8c1e224..ac7c266 100644
--- a/services/inputflinger/reader/mapper/VibratorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/VibratorInputMapper.cpp
@@ -91,8 +91,7 @@
     const VibrationElement& element = mPattern[mIndex];
     if (element.isOn()) {
 #if DEBUG_VIBRATOR
-        std::string description;
-        element.dump(description);
+        std::string description = element.toString();
         ALOGD("nextStep: sending vibrate deviceId=%d, element=%s", getDeviceId(),
               description.c_str());
 #endif
@@ -135,13 +134,13 @@
 void VibratorInputMapper::dumpPattern(std::string& dump) const {
     dump += "[";
 
-    if (mPattern.size() > 0) {
-        mPattern[0].dump(dump);
-        std::for_each(mPattern.begin() + 1, mPattern.end(), [&dump](const auto& element) {
+    for (auto it = mPattern.begin(); it != mPattern.end(); ++it) {
+        dump += it->toString();
+        if (std::next(it) != mPattern.end()) {
             dump += ", ";
-            element.dump(dump);
-        });
+        }
     }
+
     dump += "]";
 }
 
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 4b00ee4..9823a1c 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -1137,17 +1137,17 @@
 // --- InstrumentedInputReader ---
 
 class InstrumentedInputReader : public InputReader {
-    std::shared_ptr<InputDevice> mNextDevice;
+    std::queue<std::shared_ptr<InputDevice>> mNextDevices;
 
 public:
     InstrumentedInputReader(std::shared_ptr<EventHubInterface> eventHub,
                             const sp<InputReaderPolicyInterface>& policy,
                             const sp<InputListenerInterface>& listener)
-          : InputReader(eventHub, policy, listener), mNextDevice(nullptr) {}
+          : InputReader(eventHub, policy, listener) {}
 
     virtual ~InstrumentedInputReader() {}
 
-    void setNextDevice(std::shared_ptr<InputDevice> device) { mNextDevice = device; }
+    void pushNextDevice(std::shared_ptr<InputDevice> device) { mNextDevices.push(device); }
 
     std::shared_ptr<InputDevice> newDevice(int32_t deviceId, const std::string& name,
                                            const std::string& location = "") {
@@ -1164,9 +1164,9 @@
 protected:
     virtual std::shared_ptr<InputDevice> createDeviceLocked(
             int32_t eventHubId, const InputDeviceIdentifier& identifier) {
-        if (mNextDevice) {
-            std::shared_ptr<InputDevice> device(mNextDevice);
-            mNextDevice = nullptr;
+        if (!mNextDevices.empty()) {
+            std::shared_ptr<InputDevice> device(std::move(mNextDevices.front()));
+            mNextDevices.pop();
             return device;
         }
         return InputReader::createDeviceLocked(eventHubId, identifier);
@@ -1415,7 +1415,7 @@
                                                   const PropertyMap* configuration) {
         std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, name);
         FakeInputMapper& mapper = device->addMapper<FakeInputMapper>(eventHubId, sources);
-        mReader->setNextDevice(device);
+        mReader->pushNextDevice(device);
         addDevice(eventHubId, name, classes, configuration);
         return mapper;
     }
@@ -1452,7 +1452,7 @@
     std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
     // Must add at least one mapper or the device will be ignored!
     device->addMapper<FakeInputMapper>(eventHubId, AINPUT_SOURCE_KEYBOARD);
-    mReader->setNextDevice(device);
+    mReader->pushNextDevice(device);
     ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
 
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled(nullptr));
@@ -1661,7 +1661,7 @@
     std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
     // Must add at least one mapper or the device will be ignored!
     device->addMapper<FakeInputMapper>(eventHubId, AINPUT_SOURCE_KEYBOARD);
-    mReader->setNextDevice(device);
+    mReader->pushNextDevice(device);
     ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
 
     NotifyDeviceResetArgs resetArgs;
@@ -1694,7 +1694,7 @@
     std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
     // Must add at least one mapper or the device will be ignored!
     device->addMapper<FakeInputMapper>(eventHubId, AINPUT_SOURCE_KEYBOARD);
-    mReader->setNextDevice(device);
+    mReader->pushNextDevice(device);
     ASSERT_NO_FATAL_FAILURE(addDevice(deviceId, "fake", deviceClass, nullptr));
 
     NotifyDeviceResetArgs resetArgs;
@@ -1710,7 +1710,7 @@
     std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
     FakeInputMapper& mapper =
             device->addMapper<FakeInputMapper>(eventHubId, AINPUT_SOURCE_TOUCHSCREEN);
-    mReader->setNextDevice(device);
+    mReader->pushNextDevice(device);
 
     const uint8_t hdmi1 = 1;
 
@@ -1747,6 +1747,73 @@
     ASSERT_FALSE(mReader->canDispatchToDisplay(deviceId, SECONDARY_DISPLAY_ID));
 }
 
+TEST_F(InputReaderTest, WhenEnabledChanges_AllSubdevicesAreUpdated) {
+    constexpr int32_t deviceId = END_RESERVED_ID + 1000;
+    constexpr Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
+    constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1};
+    std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
+    // Must add at least one mapper or the device will be ignored!
+    device->addMapper<FakeInputMapper>(eventHubIds[0], AINPUT_SOURCE_KEYBOARD);
+    device->addMapper<FakeInputMapper>(eventHubIds[1], AINPUT_SOURCE_KEYBOARD);
+    mReader->pushNextDevice(device);
+    mReader->pushNextDevice(device);
+    ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[0], "fake1", deviceClass, nullptr));
+    ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[1], "fake2", deviceClass, nullptr));
+
+    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled(nullptr));
+
+    NotifyDeviceResetArgs resetArgs;
+    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
+    ASSERT_EQ(deviceId, resetArgs.deviceId);
+    ASSERT_TRUE(device->isEnabled());
+    ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[0]));
+    ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[1]));
+
+    disableDevice(deviceId);
+    mReader->loopOnce();
+
+    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
+    ASSERT_EQ(deviceId, resetArgs.deviceId);
+    ASSERT_FALSE(device->isEnabled());
+    ASSERT_FALSE(mFakeEventHub->isDeviceEnabled(eventHubIds[0]));
+    ASSERT_FALSE(mFakeEventHub->isDeviceEnabled(eventHubIds[1]));
+
+    enableDevice(deviceId);
+    mReader->loopOnce();
+
+    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
+    ASSERT_EQ(deviceId, resetArgs.deviceId);
+    ASSERT_TRUE(device->isEnabled());
+    ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[0]));
+    ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[1]));
+}
+
+TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToSubdeviceMappers) {
+    constexpr int32_t deviceId = END_RESERVED_ID + 1000;
+    constexpr Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
+    constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1};
+    // Add two subdevices to device
+    std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
+    FakeInputMapper& mapperDevice1 =
+            device->addMapper<FakeInputMapper>(eventHubIds[0], AINPUT_SOURCE_KEYBOARD);
+    FakeInputMapper& mapperDevice2 =
+            device->addMapper<FakeInputMapper>(eventHubIds[1], AINPUT_SOURCE_KEYBOARD);
+    mReader->pushNextDevice(device);
+    mReader->pushNextDevice(device);
+    ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[0], "fake1", deviceClass, nullptr));
+    ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[1], "fake2", deviceClass, nullptr));
+
+    mapperDevice1.setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
+    mapperDevice2.setKeyCodeState(AKEYCODE_B, AKEY_STATE_DOWN);
+
+    ASSERT_EQ(AKEY_STATE_DOWN,
+              mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_KEYBOARD, AKEYCODE_A));
+    ASSERT_EQ(AKEY_STATE_DOWN,
+              mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_KEYBOARD, AKEYCODE_B));
+    ASSERT_EQ(AKEY_STATE_UNKNOWN,
+              mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_KEYBOARD, AKEYCODE_C));
+}
+
 // --- InputReaderIntegrationTest ---
 
 // These tests create and interact with the InputReader only through its interface.
diff --git a/services/surfaceflinger/DisplayRenderArea.cpp b/services/surfaceflinger/DisplayRenderArea.cpp
index bcebf23..4bae669 100644
--- a/services/surfaceflinger/DisplayRenderArea.cpp
+++ b/services/surfaceflinger/DisplayRenderArea.cpp
@@ -85,10 +85,9 @@
                                      ui::Size reqSize, ui::Dataspace reqDataSpace,
                                      RotationFlags rotation, bool allowSecureLayers)
       : RenderArea(reqSize, CaptureFill::OPAQUE, reqDataSpace, display->getViewport(),
-                   applyDeviceOrientation(rotation, *display)),
+                   allowSecureLayers, applyDeviceOrientation(rotation, *display)),
         mDisplay(std::move(display)),
-        mSourceCrop(sourceCrop),
-        mAllowSecureLayers(allowSecureLayers) {}
+        mSourceCrop(sourceCrop) {}
 
 const ui::Transform& DisplayRenderArea::getTransform() const {
     return mTransform;
diff --git a/services/surfaceflinger/DisplayRenderArea.h b/services/surfaceflinger/DisplayRenderArea.h
index 340efb5..8840973 100644
--- a/services/surfaceflinger/DisplayRenderArea.h
+++ b/services/surfaceflinger/DisplayRenderArea.h
@@ -47,7 +47,6 @@
 
     const sp<const DisplayDevice> mDisplay;
     const Rect mSourceCrop;
-    const bool mAllowSecureLayers;
     const ui::Transform mTransform;
 };
 
diff --git a/services/surfaceflinger/LayerRenderArea.cpp b/services/surfaceflinger/LayerRenderArea.cpp
index c4f8666..555e61d 100644
--- a/services/surfaceflinger/LayerRenderArea.cpp
+++ b/services/surfaceflinger/LayerRenderArea.cpp
@@ -44,8 +44,8 @@
 
 LayerRenderArea::LayerRenderArea(SurfaceFlinger& flinger, sp<Layer> layer, const Rect& crop,
                                  ui::Size reqSize, ui::Dataspace reqDataSpace, bool childrenOnly,
-                                 const Rect& displayViewport)
-      : RenderArea(reqSize, CaptureFill::CLEAR, reqDataSpace, displayViewport),
+                                 const Rect& displayViewport, bool allowSecureLayers)
+      : RenderArea(reqSize, CaptureFill::CLEAR, reqDataSpace, displayViewport, allowSecureLayers),
         mLayer(std::move(layer)),
         mCrop(crop),
         mFlinger(flinger),
@@ -68,7 +68,7 @@
 }
 
 bool LayerRenderArea::isSecure() const {
-    return false;
+    return mAllowSecureLayers;
 }
 
 bool LayerRenderArea::needsFiltering() const {
diff --git a/services/surfaceflinger/LayerRenderArea.h b/services/surfaceflinger/LayerRenderArea.h
index 81690b9..71ff1ce 100644
--- a/services/surfaceflinger/LayerRenderArea.h
+++ b/services/surfaceflinger/LayerRenderArea.h
@@ -33,7 +33,8 @@
 class LayerRenderArea : public RenderArea {
 public:
     LayerRenderArea(SurfaceFlinger& flinger, sp<Layer> layer, const Rect& crop, ui::Size reqSize,
-                    ui::Dataspace reqDataSpace, bool childrenOnly, const Rect& displayViewport);
+                    ui::Dataspace reqDataSpace, bool childrenOnly, const Rect& displayViewport,
+                    bool allowSecureLayers);
 
     const ui::Transform& getTransform() const override;
     Rect getBounds() const override;
diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h
index a6246d9..b4bddac 100644
--- a/services/surfaceflinger/RenderArea.h
+++ b/services/surfaceflinger/RenderArea.h
@@ -24,8 +24,10 @@
     static float getCaptureFillValue(CaptureFill captureFill);
 
     RenderArea(ui::Size reqSize, CaptureFill captureFill, ui::Dataspace reqDataSpace,
-               const Rect& displayViewport, RotationFlags rotation = ui::Transform::ROT_0)
-          : mReqSize(reqSize),
+               const Rect& displayViewport, bool allowSecureLayers = false,
+               RotationFlags rotation = ui::Transform::ROT_0)
+          : mAllowSecureLayers(allowSecureLayers),
+            mReqSize(reqSize),
             mReqDataSpace(reqDataSpace),
             mCaptureFill(captureFill),
             mRotationFlags(rotation),
@@ -83,6 +85,9 @@
     // Returns the source display viewport.
     const Rect& getDisplayViewport() const { return mDisplayViewport; }
 
+protected:
+    const bool mAllowSecureLayers;
+
 private:
     const ui::Size mReqSize;
     const ui::Dataspace mReqDataSpace;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 4e0d375..9d9a4cf 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -5585,6 +5585,7 @@
     std::unordered_set<sp<Layer>, ISurfaceComposer::SpHash<Layer>> excludeLayers;
     Rect displayViewport;
     ui::Dataspace dataspace;
+    bool captureSecureLayers;
     {
         Mutex::Autolock lock(mStateLock);
 
@@ -5638,6 +5639,8 @@
 
         const ui::ColorMode colorMode = display->getCompositionDisplay()->getState().colorMode;
         dataspace = pickDataspaceFromColorMode(colorMode);
+
+        captureSecureLayers = args.captureSecureLayers && display->isSecure();
     } // mStateLock
 
     // really small crop or frameScale
@@ -5652,7 +5655,8 @@
 
     RenderAreaFuture renderAreaFuture = promise::defer([=]() -> std::unique_ptr<RenderArea> {
         return std::make_unique<LayerRenderArea>(*this, parent, crop, reqSize, dataspace,
-                                                 childrenOnly, displayViewport);
+                                                 childrenOnly, displayViewport,
+                                                 captureSecureLayers);
     });
 
     auto traverseLayers = [parent, childrenOnly,
diff --git a/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp
index 2ec4ea4..e3b9489 100644
--- a/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp
+++ b/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp
@@ -61,8 +61,10 @@
 
     std::unique_ptr<ScreenCapture> screenshot;
     // only layerB is in this range
-    sp<IBinder> parentHandle = parent->getHandle();
-    ScreenCapture::captureLayers(&screenshot, parentHandle, Rect(0, 0, 32, 32));
+    LayerCaptureArgs captureArgs;
+    captureArgs.layerHandle = parent->getHandle();
+    captureArgs.sourceCrop = {0, 0, 32, 32};
+    ScreenCapture::captureLayers(&screenshot, captureArgs);
     screenshot->expectColor(Rect(0, 0, 32, 32), Color::BLUE);
 }
 
diff --git a/services/surfaceflinger/tests/ScreenCapture_test.cpp b/services/surfaceflinger/tests/ScreenCapture_test.cpp
index 2a250ff..149e4d7 100644
--- a/services/surfaceflinger/tests/ScreenCapture_test.cpp
+++ b/services/surfaceflinger/tests/ScreenCapture_test.cpp
@@ -18,6 +18,8 @@
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wconversion"
 
+#include <private/android_filesystem_config.h>
+
 #include "LayerTransactionTest.h"
 
 namespace android {
@@ -73,16 +75,15 @@
 };
 
 TEST_F(ScreenCaptureTest, CaptureSingleLayer) {
-    auto bgHandle = mBGSurfaceControl->getHandle();
-    ScreenCapture::captureLayers(&mCapture, bgHandle);
+    LayerCaptureArgs captureArgs;
+    captureArgs.layerHandle = mBGSurfaceControl->getHandle();
+    ScreenCapture::captureLayers(&mCapture, captureArgs);
     mCapture->expectBGColor(0, 0);
     // Doesn't capture FG layer which is at 64, 64
     mCapture->expectBGColor(64, 64);
 }
 
 TEST_F(ScreenCaptureTest, CaptureLayerWithChild) {
-    auto fgHandle = mFGSurfaceControl->getHandle();
-
     sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
                                              PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
     TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
@@ -90,7 +91,9 @@
     SurfaceComposerClient::Transaction().show(child).apply(true);
 
     // Captures mFGSurfaceControl layer and its child.
-    ScreenCapture::captureLayers(&mCapture, fgHandle);
+    LayerCaptureArgs captureArgs;
+    captureArgs.layerHandle = mFGSurfaceControl->getHandle();
+    ScreenCapture::captureLayers(&mCapture, captureArgs);
     mCapture->expectFGColor(10, 10);
     mCapture->expectChildColor(0, 0);
 }
@@ -105,7 +108,10 @@
     SurfaceComposerClient::Transaction().show(child).apply(true);
 
     // Captures mFGSurfaceControl's child
-    ScreenCapture::captureChildLayers(&mCapture, fgHandle);
+    LayerCaptureArgs captureArgs;
+    captureArgs.layerHandle = fgHandle;
+    captureArgs.childrenOnly = true;
+    ScreenCapture::captureLayers(&mCapture, captureArgs);
     mCapture->checkPixel(10, 10, 0, 0, 0);
     mCapture->expectChildColor(0, 0);
 }
@@ -128,7 +134,11 @@
             .apply(true);
 
     // Child2 would be visible but its excluded, so we should see child1 color instead.
-    ScreenCapture::captureChildLayersExcluding(&mCapture, fgHandle, {child2->getHandle()});
+    LayerCaptureArgs captureArgs;
+    captureArgs.layerHandle = fgHandle;
+    captureArgs.childrenOnly = true;
+    captureArgs.excludeHandles = {child2->getHandle()};
+    ScreenCapture::captureLayers(&mCapture, captureArgs);
     mCapture->checkPixel(10, 10, 0, 0, 0);
     mCapture->checkPixel(0, 0, 200, 200, 200);
 }
@@ -156,7 +166,11 @@
             .apply(true);
 
     // Child2 would be visible but its excluded, so we should see child1 color instead.
-    ScreenCapture::captureChildLayersExcluding(&mCapture, fgHandle, {child2->getHandle()});
+    LayerCaptureArgs captureArgs;
+    captureArgs.layerHandle = fgHandle;
+    captureArgs.childrenOnly = true;
+    captureArgs.excludeHandles = {child2->getHandle()};
+    ScreenCapture::captureLayers(&mCapture, captureArgs);
     mCapture->checkPixel(10, 10, 0, 0, 0);
     mCapture->checkPixel(0, 0, 200, 200, 200);
 }
@@ -169,18 +183,17 @@
 
     SurfaceComposerClient::Transaction().show(child).apply(true);
 
-    auto childHandle = child->getHandle();
-
     // Captures child
-    ScreenCapture::captureLayers(&mCapture, childHandle, {0, 0, 10, 20});
+    LayerCaptureArgs captureArgs;
+    captureArgs.layerHandle = child->getHandle();
+    captureArgs.sourceCrop = {0, 0, 10, 20};
+    ScreenCapture::captureLayers(&mCapture, captureArgs);
     mCapture->expectColor(Rect(0, 0, 9, 9), {200, 200, 200, 255});
     // Area outside of child's bounds is transparent.
     mCapture->expectColor(Rect(0, 10, 9, 19), {0, 0, 0, 0});
 }
 
 TEST_F(ScreenCaptureTest, DontCaptureRelativeOutsideTree) {
-    auto fgHandle = mFGSurfaceControl->getHandle();
-
     sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
                                              PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
     ASSERT_NE(nullptr, child.get()) << "failed to create surface";
@@ -191,19 +204,19 @@
     SurfaceComposerClient::Transaction()
             .show(child)
             // Set relative layer above fg layer so should be shown above when computing all layers.
-            .setRelativeLayer(relative, fgHandle, 1)
+            .setRelativeLayer(relative, mFGSurfaceControl->getHandle(), 1)
             .show(relative)
             .apply(true);
 
     // Captures mFGSurfaceControl layer and its child. Relative layer shouldn't be captured.
-    ScreenCapture::captureLayers(&mCapture, fgHandle);
+    LayerCaptureArgs captureArgs;
+    captureArgs.layerHandle = mFGSurfaceControl->getHandle();
+    ScreenCapture::captureLayers(&mCapture, captureArgs);
     mCapture->expectFGColor(10, 10);
     mCapture->expectChildColor(0, 0);
 }
 
 TEST_F(ScreenCaptureTest, CaptureRelativeInTree) {
-    auto fgHandle = mFGSurfaceControl->getHandle();
-
     sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
                                              PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
     sp<SurfaceControl> relative = createSurface(mClient, "Relative surface", 10, 10,
@@ -222,7 +235,9 @@
 
     // Captures mFGSurfaceControl layer and its children. Relative layer is a child of fg so its
     // relative value should be taken into account, placing it above child layer.
-    ScreenCapture::captureLayers(&mCapture, fgHandle);
+    LayerCaptureArgs captureArgs;
+    captureArgs.layerHandle = mFGSurfaceControl->getHandle();
+    ScreenCapture::captureLayers(&mCapture, captureArgs);
     mCapture->expectFGColor(10, 10);
     // Relative layer is showing on top of child layer
     mCapture->expectColor(Rect(0, 0, 9, 9), {100, 100, 100, 255});
@@ -232,10 +247,10 @@
     sp<SurfaceControl> child = createColorLayer("Child layer", Color::RED, mFGSurfaceControl.get());
     SurfaceComposerClient::Transaction().show(child).apply(true);
 
-    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
-    Rect sourceCrop(0, 0, 10, 10);
-    sp<IBinder> childHandle = child->getHandle();
-    ScreenCapture::captureLayers(&mCapture, childHandle, sourceCrop);
+    LayerCaptureArgs captureArgs;
+    captureArgs.layerHandle = child->getHandle();
+    captureArgs.sourceCrop = {0, 0, 10, 10};
+    ScreenCapture::captureLayers(&mCapture, captureArgs);
 
     mCapture->expectColor(Rect(0, 0, 9, 9), Color::RED);
 }
@@ -245,10 +260,9 @@
     Rect layerCrop(0, 0, 10, 10);
     SurfaceComposerClient::Transaction().setCrop_legacy(child, layerCrop).show(child).apply(true);
 
-    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
-    sp<GraphicBuffer> outBuffer;
-    sp<IBinder> childHandle = child->getHandle();
-    ScreenCapture::captureLayers(&mCapture, childHandle);
+    LayerCaptureArgs captureArgs;
+    captureArgs.layerHandle = child->getHandle();
+    ScreenCapture::captureLayers(&mCapture, captureArgs);
 
     mCapture->expectColor(Rect(0, 0, 9, 9), Color::RED);
 }
@@ -289,8 +303,6 @@
 }
 
 TEST_F(ScreenCaptureTest, CaptureLayerWithGrandchild) {
-    auto fgHandle = mFGSurfaceControl->getHandle();
-
     sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
                                              PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
     TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
@@ -306,7 +318,9 @@
             .apply(true);
 
     // Captures mFGSurfaceControl, its child, and the grandchild.
-    ScreenCapture::captureLayers(&mCapture, fgHandle);
+    LayerCaptureArgs captureArgs;
+    captureArgs.layerHandle = mFGSurfaceControl->getHandle();
+    ScreenCapture::captureLayers(&mCapture, captureArgs);
     mCapture->expectFGColor(10, 10);
     mCapture->expectChildColor(0, 0);
     mCapture->checkPixel(5, 5, 50, 50, 50);
@@ -316,12 +330,13 @@
     sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
                                              PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
     TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
-    auto childHandle = child->getHandle();
 
     SurfaceComposerClient::Transaction().setPosition(child, 5, 5).show(child).apply(true);
 
     // Captures only the child layer, and not the parent.
-    ScreenCapture::captureLayers(&mCapture, childHandle);
+    LayerCaptureArgs captureArgs;
+    captureArgs.layerHandle = child->getHandle();
+    ScreenCapture::captureLayers(&mCapture, captureArgs);
     mCapture->expectChildColor(0, 0);
     mCapture->expectChildColor(9, 9);
 }
@@ -342,10 +357,10 @@
             .show(grandchild)
             .apply(true);
 
-    auto grandchildHandle = grandchild->getHandle();
-
     // Captures only the grandchild.
-    ScreenCapture::captureLayers(&mCapture, grandchildHandle);
+    LayerCaptureArgs captureArgs;
+    captureArgs.layerHandle = grandchild->getHandle();
+    ScreenCapture::captureLayers(&mCapture, captureArgs);
     mCapture->checkPixel(0, 0, 50, 50, 50);
     mCapture->checkPixel(4, 4, 50, 50, 50);
 }
@@ -364,18 +379,18 @@
             .show(blueLayer)
             .apply(true);
 
-    auto redLayerHandle = redLayer->getHandle();
-
     // Capturing full screen should have both red and blue are visible.
-    ScreenCapture::captureLayers(&mCapture, redLayerHandle);
+    LayerCaptureArgs captureArgs;
+    captureArgs.layerHandle = redLayer->getHandle();
+    ScreenCapture::captureLayers(&mCapture, captureArgs);
     mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE);
     // red area below the blue area
     mCapture->expectColor(Rect(0, 30, 59, 59), Color::RED);
     // red area to the right of the blue area
     mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED);
 
-    const Rect crop = Rect(0, 0, 30, 30);
-    ScreenCapture::captureLayers(&mCapture, redLayerHandle, crop);
+    captureArgs.sourceCrop = {0, 0, 30, 30};
+    ScreenCapture::captureLayers(&mCapture, captureArgs);
     // Capturing the cropped screen, cropping out the shown red area, should leave only the blue
     // area visible.
     mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE);
@@ -396,17 +411,18 @@
             .show(blueLayer)
             .apply(true);
 
-    auto redLayerHandle = redLayer->getHandle();
-
     // Capturing full screen should have both red and blue are visible.
-    ScreenCapture::captureLayers(&mCapture, redLayerHandle);
+    LayerCaptureArgs captureArgs;
+    captureArgs.layerHandle = redLayer->getHandle();
+    ScreenCapture::captureLayers(&mCapture, captureArgs);
     mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE);
     // red area below the blue area
     mCapture->expectColor(Rect(0, 30, 59, 59), Color::RED);
     // red area to the right of the blue area
     mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED);
 
-    ScreenCapture::captureLayers(&mCapture, redLayerHandle, Rect::EMPTY_RECT, 0.5);
+    captureArgs.frameScale = 0.5f;
+    ScreenCapture::captureLayers(&mCapture, captureArgs);
     // Capturing the downsized area (30x30) should leave both red and blue but in a smaller area.
     mCapture->expectColor(Rect(0, 0, 14, 14), Color::BLUE);
     // red area below the blue area
@@ -435,6 +451,49 @@
     ASSERT_EQ(NAME_NOT_FOUND, sf->captureLayers(args, captureResults));
 }
 
+TEST_F(ScreenCaptureTest, CaputureSecureLayer) {
+    sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60, 0);
+    sp<SurfaceControl> secureLayer =
+            createLayer(String8("Secure surface"), 30, 30,
+                        ISurfaceComposerClient::eSecure |
+                                ISurfaceComposerClient::eFXSurfaceBufferQueue,
+                        redLayer.get());
+    ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60));
+    ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(secureLayer, Color::BLUE, 30, 30));
+
+    auto redLayerHandle = redLayer->getHandle();
+    Transaction()
+            .show(redLayer)
+            .show(secureLayer)
+            .setLayerStack(redLayer, 0)
+            .setLayer(redLayer, INT32_MAX)
+            .apply();
+
+    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+
+    LayerCaptureArgs args;
+    args.layerHandle = redLayerHandle;
+    args.childrenOnly = false;
+    ScreenCaptureResults captureResults;
+
+    // Call from outside system with secure layers will result in permission denied
+    ASSERT_EQ(PERMISSION_DENIED, sf->captureLayers(args, captureResults));
+
+    UIDFaker f(AID_SYSTEM);
+
+    // From system request, only red layer will be screenshot since the blue layer is secure.
+    // Black will be present where the secure layer is.
+    ScreenCapture::captureLayers(&mCapture, args);
+    mCapture->expectColor(Rect(0, 0, 30, 30), Color::BLACK);
+    mCapture->expectColor(Rect(30, 30, 60, 60), Color::RED);
+
+    // Passing flag secure so the blue layer should be screenshot too.
+    args.captureSecureLayers = true;
+    ScreenCapture::captureLayers(&mCapture, args);
+    mCapture->expectColor(Rect(0, 0, 30, 30), Color::BLUE);
+    mCapture->expectColor(Rect(30, 30, 60, 60), Color::RED);
+}
+
 // In the following tests we verify successful skipping of a parent layer,
 // so we use the same verification logic and only change how we mutate
 // the parent layer to verify that various properties are ignored.
@@ -456,8 +515,10 @@
 
         // Verify child layer does not inherit any of the properties of its
         // parent when its screenshot is captured.
-        auto fgHandle = mFGSurfaceControl->getHandle();
-        ScreenCapture::captureChildLayers(&mCapture, fgHandle);
+        LayerCaptureArgs captureArgs;
+        captureArgs.layerHandle = mFGSurfaceControl->getHandle();
+        captureArgs.childrenOnly = true;
+        ScreenCapture::captureLayers(&mCapture, captureArgs);
         mCapture->checkPixel(10, 10, 0, 0, 0);
         mCapture->expectChildColor(0, 0);
 
diff --git a/services/surfaceflinger/tests/utils/ScreenshotUtils.h b/services/surfaceflinger/tests/utils/ScreenshotUtils.h
index d73506b..56628f8 100644
--- a/services/surfaceflinger/tests/utils/ScreenshotUtils.h
+++ b/services/surfaceflinger/tests/utils/ScreenshotUtils.h
@@ -43,54 +43,13 @@
         *sc = std::make_unique<ScreenCapture>(captureResults.buffer);
     }
 
-    static void captureLayers(std::unique_ptr<ScreenCapture>* sc, sp<IBinder>& parentHandle,
-                              Rect crop = Rect::EMPTY_RECT, float frameScale = 1.0) {
+    static void captureLayers(std::unique_ptr<ScreenCapture>* sc,
+                              const LayerCaptureArgs& captureArgs) {
         sp<ISurfaceComposer> sf(ComposerService::getComposerService());
         SurfaceComposerClient::Transaction().apply(true);
 
-        LayerCaptureArgs args;
-        args.layerHandle = parentHandle;
-        args.sourceCrop = crop;
-        args.frameScale = frameScale;
-        args.childrenOnly = false;
-
         ScreenCaptureResults captureResults;
-        ASSERT_EQ(NO_ERROR, sf->captureLayers(args, captureResults));
-        *sc = std::make_unique<ScreenCapture>(captureResults.buffer);
-    }
-
-    static void captureChildLayers(std::unique_ptr<ScreenCapture>* sc, sp<IBinder>& parentHandle,
-                                   Rect crop = Rect::EMPTY_RECT, float frameScale = 1.0) {
-        sp<ISurfaceComposer> sf(ComposerService::getComposerService());
-        SurfaceComposerClient::Transaction().apply(true);
-
-        LayerCaptureArgs args;
-        args.layerHandle = parentHandle;
-        args.sourceCrop = crop;
-        args.frameScale = frameScale;
-        args.childrenOnly = true;
-
-        ScreenCaptureResults captureResults;
-        ASSERT_EQ(NO_ERROR, sf->captureLayers(args, captureResults));
-        *sc = std::make_unique<ScreenCapture>(captureResults.buffer);
-    }
-
-    static void captureChildLayersExcluding(
-            std::unique_ptr<ScreenCapture>* sc, sp<IBinder>& parentHandle,
-            std::unordered_set<sp<IBinder>, ISurfaceComposer::SpHash<IBinder>> excludeLayers) {
-        sp<ISurfaceComposer> sf(ComposerService::getComposerService());
-        SurfaceComposerClient::Transaction().apply(true);
-
-        LayerCaptureArgs args;
-        args.layerHandle = parentHandle;
-        args.pixelFormat = ui::PixelFormat::RGBA_8888;
-        args.sourceCrop = Rect::EMPTY_RECT;
-        args.excludeHandles = excludeLayers;
-        args.frameScale = 1.0f;
-        args.childrenOnly = true;
-
-        ScreenCaptureResults captureResults;
-        ASSERT_EQ(NO_ERROR, sf->captureLayers(args, captureResults));
+        ASSERT_EQ(NO_ERROR, sf->captureLayers(captureArgs, captureResults));
         *sc = std::make_unique<ScreenCapture>(captureResults.buffer);
     }