Merge "Vulkan: swapchain images to be early released must be idle"
diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp
index 3467898..67a77f6 100644
--- a/cmds/dumpsys/tests/dumpsys_test.cpp
+++ b/cmds/dumpsys/tests/dumpsys_test.cpp
@@ -55,6 +55,7 @@
     MOCK_METHOD1(listServices, Vector<String16>(int));
     MOCK_METHOD1(waitForService, sp<IBinder>(const String16&));
     MOCK_METHOD1(isDeclared, bool(const String16&));
+    MOCK_METHOD1(getDeclaredInstances, Vector<String16>(const String16&));
   protected:
     MOCK_METHOD0(onAsBinder, IBinder*());
 };
diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp
index 2c3efe5..99cb93a 100644
--- a/cmds/lshal/Lshal.cpp
+++ b/cmds/lshal/Lshal.cpp
@@ -141,7 +141,7 @@
         }
     }
 
-    PipeRelay relay(out);
+    PipeRelay relay(out, err, interfaceName, instanceName);
 
     if (relay.initCheck() != OK) {
         std::string msg = "PipeRelay::initCheck() FAILED w/ " + std::to_string(relay.initCheck());
diff --git a/cmds/lshal/PipeRelay.cpp b/cmds/lshal/PipeRelay.cpp
index 820679f..4e97636 100644
--- a/cmds/lshal/PipeRelay.cpp
+++ b/cmds/lshal/PipeRelay.cpp
@@ -23,7 +23,6 @@
 
 #include <atomic>
 
-#include <android-base/logging.h>
 #include <utils/Thread.h>
 
 namespace android {
@@ -31,8 +30,15 @@
 
 static constexpr struct timeval READ_TIMEOUT { .tv_sec = 1, .tv_usec = 0 };
 
+static std::string getThreadName(std::string interfaceName, const std::string &instanceName) {
+    auto dot = interfaceName.rfind(".");
+    if (dot != std::string::npos) interfaceName = interfaceName.substr(dot + 1);
+    return "RelayThread_" + interfaceName + "_" + instanceName;
+}
+
 struct PipeRelay::RelayThread : public Thread {
-    explicit RelayThread(int fd, std::ostream &os);
+    explicit RelayThread(int fd, std::ostream &os, const NullableOStream<std::ostream> &err,
+                         const std::string &fqName);
 
     bool threadLoop() override;
     void setFinished();
@@ -40,6 +46,7 @@
 private:
     int mFd;
     std::ostream &mOutStream;
+    NullableOStream<std::ostream> mErrStream;
 
     // If we were to use requestExit() and exitPending() instead, threadLoop()
     // may not run at all by the time ~PipeRelay is called (i.e. debug() has
@@ -47,13 +54,17 @@
     // read() are executed until data are drained.
     std::atomic_bool mFinished;
 
+    std::string mFqName;
+
     DISALLOW_COPY_AND_ASSIGN(RelayThread);
 };
 
 ////////////////////////////////////////////////////////////////////////////////
 
-PipeRelay::RelayThread::RelayThread(int fd, std::ostream &os)
-      : mFd(fd), mOutStream(os), mFinished(false) {}
+PipeRelay::RelayThread::RelayThread(int fd, std::ostream &os,
+                                    const NullableOStream<std::ostream> &err,
+                                    const std::string &fqName)
+      : mFd(fd), mOutStream(os), mErrStream(err), mFinished(false), mFqName(fqName) {}
 
 bool PipeRelay::RelayThread::threadLoop() {
     char buffer[1024];
@@ -66,13 +77,14 @@
 
     int res = TEMP_FAILURE_RETRY(select(mFd + 1, &set, nullptr, nullptr, &timeout));
     if (res < 0) {
-        PLOG(INFO) << "select() failed";
+        mErrStream << "debug " << mFqName << ": select() failed";
         return false;
     }
 
     if (res == 0 || !FD_ISSET(mFd, &set)) {
         if (mFinished) {
-            LOG(WARNING) << "debug: timeout reading from pipe, output may be truncated.";
+            mErrStream << "debug " << mFqName
+                       << ": timeout reading from pipe, output may be truncated.";
             return false;
         }
         // timeout, but debug() has not returned, so wait for HAL to finish.
@@ -83,7 +95,7 @@
     ssize_t n = TEMP_FAILURE_RETRY(read(mFd, buffer, sizeof(buffer)));
 
     if (n < 0) {
-        PLOG(ERROR) << "read() failed";
+        mErrStream << "debug " << mFqName << ": read() failed";
     }
 
     if (n <= 0) {
@@ -101,8 +113,9 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-PipeRelay::PipeRelay(std::ostream &os)
-    : mInitCheck(NO_INIT) {
+PipeRelay::PipeRelay(std::ostream &os, const NullableOStream<std::ostream> &err,
+                     const std::string &interfaceName, const std::string &instanceName)
+      : mInitCheck(NO_INIT) {
     int res = pipe(mFds);
 
     if (res < 0) {
@@ -110,8 +123,8 @@
         return;
     }
 
-    mThread = new RelayThread(mFds[0], os);
-    mInitCheck = mThread->run("RelayThread");
+    mThread = new RelayThread(mFds[0], os, err, interfaceName + "/" + instanceName);
+    mInitCheck = mThread->run(getThreadName(interfaceName, instanceName).c_str());
 }
 
 void PipeRelay::CloseFd(int *fd) {
diff --git a/cmds/lshal/PipeRelay.h b/cmds/lshal/PipeRelay.h
index 835016041..bd994b4 100644
--- a/cmds/lshal/PipeRelay.h
+++ b/cmds/lshal/PipeRelay.h
@@ -21,6 +21,8 @@
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
 
+#include "NullableOStream.h"
+
 namespace android {
 namespace lshal {
 
@@ -28,7 +30,10 @@
  * written to the "write"-end of the pair to the specified output stream "os".
  */
 struct PipeRelay {
-    explicit PipeRelay(std::ostream &os);
+    explicit PipeRelay(std::ostream& os,
+                       const NullableOStream<std::ostream>& err,
+                       const std::string& interfaceName,
+                       const std::string& instanceName);
     ~PipeRelay();
 
     status_t initCheck() const;
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index e80c321..c8355e2 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -37,6 +37,27 @@
 namespace android {
 
 #ifndef VENDORSERVICEMANAGER
+struct ManifestWithDescription {
+    std::shared_ptr<const vintf::HalManifest> manifest;
+    const char* description;
+};
+// func true -> stop search and forEachManifest will return true
+static bool forEachManifest(const std::function<bool(const ManifestWithDescription&)>& func) {
+    for (const ManifestWithDescription& mwd : {
+            ManifestWithDescription{ vintf::VintfObject::GetDeviceHalManifest(), "device" },
+            ManifestWithDescription{ vintf::VintfObject::GetFrameworkHalManifest(), "framework" },
+        }) {
+        if (mwd.manifest == nullptr) {
+          LOG(ERROR) << "NULL VINTF MANIFEST!: " << mwd.description;
+          // note, we explicitly do not retry here, so that we can detect VINTF
+          // or other bugs (b/151696835)
+          continue;
+        }
+        if (func(mwd)) return true;
+    }
+    return false;
+}
+
 static bool isVintfDeclared(const std::string& name) {
     size_t firstSlash = name.find('/');
     size_t lastDot = name.rfind('.', firstSlash);
@@ -49,31 +70,41 @@
     const std::string iface = name.substr(lastDot+1, firstSlash-lastDot-1);
     const std::string instance = name.substr(firstSlash+1);
 
-    struct ManifestWithDescription {
-        std::shared_ptr<const vintf::HalManifest> manifest;
-        const char* description;
-    };
-    for (const ManifestWithDescription& mwd : {
-            ManifestWithDescription{ vintf::VintfObject::GetDeviceHalManifest(), "device" },
-            ManifestWithDescription{ vintf::VintfObject::GetFrameworkHalManifest(), "framework" },
-        }) {
-        if (mwd.manifest == nullptr) {
-          LOG(ERROR) << "NULL VINTF MANIFEST!: " << mwd.description;
-          // note, we explicitly do not retry here, so that we can detect VINTF
-          // or other bugs (b/151696835)
-          continue;
-        }
+    bool found = forEachManifest([&] (const ManifestWithDescription& mwd) {
         if (mwd.manifest->hasAidlInstance(package, iface, instance)) {
             LOG(INFO) << "Found " << name << " in " << mwd.description << " VINTF manifest.";
             return true;
         }
+        return false;  // continue
+    });
+
+    if (!found) {
+        // Although it is tested, explicitly rebuilding qualified name, in case it
+        // becomes something unexpected.
+        LOG(ERROR) << "Could not find " << package << "." << iface << "/" << instance
+                   << " in the VINTF manifest.";
     }
 
-    // Although it is tested, explicitly rebuilding qualified name, in case it
-    // becomes something unexpected.
-    LOG(ERROR) << "Could not find " << package << "." << iface << "/" << instance
-               << " in the VINTF manifest.";
-    return false;
+    return found;
+}
+
+static std::vector<std::string> getVintfInstances(const std::string& interface) {
+    size_t lastDot = interface.rfind('.');
+    if (lastDot == std::string::npos) {
+        LOG(ERROR) << "VINTF interfaces require names in Java package format (e.g. some.package.foo.IFoo) but got: " << interface;
+        return {};
+    }
+    const std::string package = interface.substr(0, lastDot);
+    const std::string iface = interface.substr(lastDot+1);
+
+    std::vector<std::string> ret;
+    (void)forEachManifest([&](const ManifestWithDescription& mwd) {
+        auto instances = mwd.manifest->getAidlInstances(package, iface);
+        ret.insert(ret.end(), instances.begin(), instances.end());
+        return false;  // continue
+    });
+
+    return ret;
 }
 
 static bool meetsDeclarationRequirements(const sp<IBinder>& binder, const std::string& name) {
@@ -331,6 +362,30 @@
     return Status::ok();
 }
 
+binder::Status ServiceManager::getDeclaredInstances(const std::string& interface, std::vector<std::string>* outReturn) {
+    auto ctx = mAccess->getCallingContext();
+
+    std::vector<std::string> allInstances;
+#ifndef VENDORSERVICEMANAGER
+    allInstances = getVintfInstances(interface);
+#endif
+
+    outReturn->clear();
+
+    for (const std::string& instance : allInstances) {
+        // TODO(b/169275998): allow checking policy only once for the interface
+        if (mAccess->canFind(ctx, interface + "/" + instance)) {
+            outReturn->push_back(instance);
+        }
+    }
+
+    if (outReturn->size() == 0 && allInstances.size() != 0) {
+        return Status::fromExceptionCode(Status::EX_SECURITY);
+    }
+
+    return Status::ok();
+}
+
 void ServiceManager::removeRegistrationCallback(const wp<IBinder>& who,
                                     ServiceCallbackMap::iterator* it,
                                     bool* found) {
diff --git a/cmds/servicemanager/ServiceManager.h b/cmds/servicemanager/ServiceManager.h
index a2fc5a8..9f43eb4 100644
--- a/cmds/servicemanager/ServiceManager.h
+++ b/cmds/servicemanager/ServiceManager.h
@@ -44,6 +44,7 @@
                                               const sp<IServiceCallback>& callback) override;
 
     binder::Status isDeclared(const std::string& name, bool* outReturn) override;
+    binder::Status getDeclaredInstances(const std::string& interface, std::vector<std::string>* outReturn) override;
     binder::Status registerClientCallback(const std::string& name, const sp<IBinder>& service,
                                           const sp<IClientCallback>& cb) override;
     binder::Status tryUnregisterService(const std::string& name, const sp<IBinder>& binder) override;
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 9aa82d9..6d728dc 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -74,6 +74,7 @@
     Vector<String16> listServices(int dumpsysPriority) override;
     sp<IBinder> waitForService(const String16& name16) override;
     bool isDeclared(const String16& name) override;
+    Vector<String16> getDeclaredInstances(const String16& interface) override;
 
     // for legacy ABI
     const String16& getInterfaceDescriptor() const override {
@@ -373,4 +374,18 @@
     return declared;
 }
 
+Vector<String16> ServiceManagerShim::getDeclaredInstances(const String16& interface) {
+    std::vector<std::string> out;
+    if (!mTheRealServiceManager->getDeclaredInstances(String8(interface).c_str(), &out).isOk()) {
+        return {};
+    }
+
+    Vector<String16> res;
+    res.setCapacity(out.size());
+    for (const std::string& instance : out) {
+        res.push(String16(instance.c_str()));
+    }
+    return res;
+}
+
 } // namespace android
diff --git a/libs/binder/aidl/android/os/IServiceManager.aidl b/libs/binder/aidl/android/os/IServiceManager.aidl
index ff15460..2b1e492 100644
--- a/libs/binder/aidl/android/os/IServiceManager.aidl
+++ b/libs/binder/aidl/android/os/IServiceManager.aidl
@@ -99,6 +99,14 @@
     boolean isDeclared(@utf8InCpp String name);
 
     /**
+     * Returns all declared instances for a particular interface.
+     *
+     * For instance, if 'android.foo.IFoo/foo' is declared, and 'android.foo.IFoo' is
+     * passed here, then ["foo"] would be returned.
+     */
+    @utf8InCpp String[] getDeclaredInstances(@utf8InCpp String iface);
+
+    /**
      * Request a callback when the number of clients of the service changes.
      * Used by LazyServiceRegistrar to dynamically stop services that have no clients.
      */
diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h
index 1d520c1..3c5ccc1 100644
--- a/libs/binder/include/binder/IServiceManager.h
+++ b/libs/binder/include/binder/IServiceManager.h
@@ -96,6 +96,11 @@
      * service.
      */
     virtual bool isDeclared(const String16& name) = 0;
+
+    /**
+     * Get all instances of a service as declared in the VINTF manifest
+     */
+    virtual Vector<String16> getDeclaredInstances(const String16& interface) = 0;
 };
 
 sp<IServiceManager> defaultServiceManager();
diff --git a/libs/binder/ndk/include_cpp/android/binder_auto_utils.h b/libs/binder/ndk/include_cpp/android/binder_auto_utils.h
index f59bb75..439b019 100644
--- a/libs/binder/ndk/include_cpp/android/binder_auto_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_auto_utils.h
@@ -199,6 +199,9 @@
    public:
     /**
      * Takes ownership of a.
+     *
+     * WARNING: this constructor is only expected to be used when reading a
+     *     status value. Use `ScopedAStatus::ok()` instead.
      */
     explicit ScopedAStatus(AStatus* a = nullptr) : ScopedAResource(a) {}
     ~ScopedAStatus() {}
diff --git a/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h b/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h
new file mode 100644
index 0000000..6701518
--- /dev/null
+++ b/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+/**
+ * @addtogroup NdkBinder
+ * @{
+ */
+
+/**
+ * @file binder_parcelable_utils.h
+ * @brief Helper for parcelable.
+ */
+
+#pragma once
+
+namespace ndk {
+// Also see Parcelable.h in libbinder.
+typedef int32_t parcelable_stability_t;
+enum {
+    STABILITY_LOCAL,
+    STABILITY_VINTF,  // corresponds to @VintfStability
+};
+}  // namespace ndk
+
+/** @} */
diff --git a/libs/binder/ndk/status.cpp b/libs/binder/ndk/status.cpp
index 4fd59a2..a8ae441 100644
--- a/libs/binder/ndk/status.cpp
+++ b/libs/binder/ndk/status.cpp
@@ -23,7 +23,8 @@
 using ::android::binder::Status;
 
 AStatus* AStatus_newOk() {
-    return new AStatus();
+    static AStatus status = AStatus();
+    return &status;
 }
 
 AStatus* AStatus_fromExceptionCode(binder_exception_t exception) {
@@ -78,7 +79,9 @@
 }
 
 void AStatus_delete(AStatus* status) {
-    delete status;
+    if (status != AStatus_newOk()) {
+        delete status;
+    }
 }
 
 binder_status_t PruneStatusT(status_t status) {
diff --git a/libs/binder/rust/Android.bp b/libs/binder/rust/Android.bp
index 0234820..dc8270e 100644
--- a/libs/binder/rust/Android.bp
+++ b/libs/binder/rust/Android.bp
@@ -28,11 +28,8 @@
 rust_bindgen {
     name: "libbinder_ndk_bindgen",
     crate_name: "binder_ndk_bindgen",
-    wrapper_src: "sys/BinderBindings.h",
+    wrapper_src: "sys/BinderBindings.hpp",
     source_stem: "bindings",
-    cflags: [
-        "-x c++",
-    ],
     bindgen_flags: [
         // Unfortunately the only way to specify the rust_non_exhaustive enum
         // style for a type is to make it the default
diff --git a/libs/binder/rust/sys/BinderBindings.h b/libs/binder/rust/sys/BinderBindings.hpp
similarity index 100%
rename from libs/binder/rust/sys/BinderBindings.h
rename to libs/binder/rust/sys/BinderBindings.hpp
diff --git a/libs/fakeservicemanager/ServiceManager.cpp b/libs/fakeservicemanager/ServiceManager.cpp
index 6964324..4ecbe53 100644
--- a/libs/fakeservicemanager/ServiceManager.cpp
+++ b/libs/fakeservicemanager/ServiceManager.cpp
@@ -61,4 +61,16 @@
     return mNameToService.find(name) != mNameToService.end();
 }
 
+Vector<String16> ServiceManager::getDeclaredInstances(const String16& name) {
+    Vector<String16> out;
+    const String16 prefix = name + String16("/");
+    for (const auto& [registeredName, service] : mNameToService) {
+        (void) service;
+        if (registeredName.startsWith(prefix)) {
+            out.add(String16(registeredName.string() + prefix.size()));
+        }
+    }
+    return out;
+}
+
 }  // namespace android
diff --git a/libs/fakeservicemanager/ServiceManager.h b/libs/fakeservicemanager/ServiceManager.h
index 62311d4..4ef47fb 100644
--- a/libs/fakeservicemanager/ServiceManager.h
+++ b/libs/fakeservicemanager/ServiceManager.h
@@ -30,42 +30,23 @@
 public:
     ServiceManager();
 
-    /**
-     * Equivalent of checkService.
-     */
     sp<IBinder> getService( const String16& name) const override;
 
-    /**
-     * Retrieve an existing service, non-blocking.
-     */
     sp<IBinder> checkService( const String16& name) const override;
 
-    /**
-     * Register a service.
-     */
     status_t addService(const String16& name, const sp<IBinder>& service,
                         bool allowIsolated = false,
                         int dumpsysFlags = DUMP_FLAG_PRIORITY_DEFAULT) override;
 
-    /**
-     * Return list of all existing services.
-     */
     Vector<String16> listServices(int dumpsysFlags = 0) override;
 
     IBinder* onAsBinder() override;
 
-    /**
-     * Effectively no-oped in this implementation - equivalent to checkService.
-     */
     sp<IBinder> waitForService(const String16& name) override;
 
-    /**
-     * Check if a service is declared (e.g. VINTF manifest).
-     *
-     * If this returns true, waitForService should always be able to return the
-     * service.
-     */
-     bool isDeclared(const String16& name) override;
+    bool isDeclared(const String16& name) override;
+
+    Vector<String16> getDeclaredInstances(const String16& iface) override;
 
 private:
     std::map<String16, sp<IBinder>> mNameToService;