Merge "Clear dlerror before executing anything."
diff --git a/base/HidlSupport.cpp b/base/HidlSupport.cpp
index ec5b18f..91d56e7 100644
--- a/base/HidlSupport.cpp
+++ b/base/HidlSupport.cpp
@@ -22,56 +22,40 @@
 #include <android-base/logging.h>
 #include <android-base/parseint.h>
 #include <hidl-util/FQName.h>
-#include <vintf/HalManifest.h>
+#include <vintf/VintfObject.h>
 #include <vintf/parse_string.h>
 
 namespace android {
 namespace hardware {
-vintf::Transport getTransportForFrameworkPackages(const std::string &name) {
-    // TODO(b/34772739): move to framework vintf
-    const static std::unordered_map<std::string, vintf::Transport> sTransports {
-        {"android.hidl.manager@1.0::IServiceManager", vintf::Transport::HWBINDER},
-        {"android.hidl.allocator@1.0::IAllocator"   , vintf::Transport::HWBINDER},
-        {"android.hidl.memory@1.0::IMapper"         , vintf::Transport::PASSTHROUGH},
-        {"android.hidl.memory@1.0::IMemory"         , vintf::Transport::PASSTHROUGH},
-    };
-    auto it = sTransports.find(name);
-    if (it == sTransports.end()) {
-        LOG(ERROR) << "getTransportForFrameworkPackages: Cannot find entry "
-                     << name << " in the static map. Using default transport.";
-        return vintf::Transport::EMPTY;
-    } else {
-        LOG(INFO) << "getTransportForFrameworkPackages: " << name
-                  << " declares transport method " << to_string(it->second);
-    }
-    return it->second;
-}
 
-vintf::Transport getTransportForHals(const FQName &fqName) {
-    const std::string package = fqName.package();
-    const vintf::HalManifest *vm = vintf::HalManifest::Get();
+vintf::Transport getTransportFromManifest(
+        const FQName &fqName, const std::string &instanceName,
+        const std::string &manifestName,
+        const vintf::HalManifest *vm) {
     if (vm == nullptr) {
-        LOG(WARNING) << "getTransportForHals: No VINTF defined, using default transport for "
-                     << fqName.string() << ".";
+        LOG(WARNING) << "getTransportFromManifest: No " << manifestName << " manifest defined, "
+                     << "using default transport for " << fqName.string();
         return vintf::Transport::EMPTY;
     }
-    vintf::Transport tr = vm->getTransport(package,
-            vintf::Version{fqName.getPackageMajorVersion(), fqName.getPackageMinorVersion()});
+    vintf::Transport tr = vm->getTransport(fqName.package(),
+            vintf::Version{fqName.getPackageMajorVersion(), fqName.getPackageMinorVersion()},
+            fqName.name(), instanceName);
     if (tr == vintf::Transport::EMPTY) {
-        LOG(WARNING) << "getTransportForHals: Cannot find entry "
-                     << package << fqName.atVersion()
-                     << " in vendor interface manifest. Using default transport.";
+        LOG(WARNING) << "getTransportFromManifest: Cannot find entry "
+                     << fqName.string()
+                     << " in " << manifestName << " manifest, using default transport.";
     } else {
-        LOG(INFO) << "getTransportForHals: " << package << fqName.atVersion()
-                  << " declares transport method " << to_string(tr);
+        LOG(DEBUG) << "getTransportFromManifest: " << fqName.string()
+                   << " declares transport method " << to_string(tr)
+                   << " in " << manifestName << " manifest";
     }
     return tr;
 }
 
-vintf::Transport getTransport(const std::string &name) {
-    FQName fqName(name);
+vintf::Transport getTransport(const std::string &interfaceName, const std::string &instanceName) {
+    FQName fqName(interfaceName);
     if (!fqName.isValid()) {
-        LOG(ERROR) << "getTransport: " << name << " is not a valid fully-qualified name.";
+        LOG(ERROR) << "getTransport: " << interfaceName << " is not a valid fully-qualified name.";
         return vintf::Transport::EMPTY;
     }
     if (!fqName.hasVersion()) {
@@ -79,10 +63,18 @@
                    << " does not specify a version. Using default transport.";
         return vintf::Transport::EMPTY;
     }
-    if (fqName.inPackage("android.hidl")) {
-        return getTransportForFrameworkPackages(name);
+    if (fqName.name().empty()) {
+        LOG(ERROR) << "getTransport: " << fqName.string()
+                   << " does not specify an interface name. Using default transport.";
+        return vintf::Transport::EMPTY;
     }
-    return getTransportForHals(fqName);
+    // TODO(b/34772739): modify the list if other packages are added to system/manifest.xml
+    if (fqName.inPackage("android.hidl")) {
+        return getTransportFromManifest(fqName, instanceName, "framework",
+                vintf::VintfObject::GetFrameworkHalManifest());
+    }
+    return getTransportFromManifest(fqName, instanceName, "device",
+            vintf::VintfObject::GetDeviceHalManifest());
 }
 
 hidl_handle::hidl_handle() {
@@ -239,6 +231,11 @@
 
 hidl_string &hidl_string::operator=(const char *s) {
     clear();
+
+    if (s == nullptr) {
+        return *this;
+    }
+
     copyFrom(s, strlen(s));
     return *this;
 }
@@ -275,11 +272,12 @@
 void hidl_string::moveFrom(hidl_string &&other) {
     // assume my resources are freed.
 
-    mBuffer = other.mBuffer;
+    mBuffer = std::move(other.mBuffer);
     mSize = other.mSize;
     mOwnsBuffer = other.mOwnsBuffer;
 
     other.mOwnsBuffer = false;
+    other.clear();
 }
 
 void hidl_string::clear() {
diff --git a/base/include/hidl/HidlSupport.h b/base/include/hidl/HidlSupport.h
index d22c257..a16701b 100644
--- a/base/include/hidl/HidlSupport.h
+++ b/base/include/hidl/HidlSupport.h
@@ -57,9 +57,11 @@
 namespace hardware {
 
 // Get transport method from vendor interface manifest.
-// name has the format "android.hardware.foo@1.0::IFoo"
+// interfaceName has the format "android.hardware.foo@1.0::IFoo"
+// instanceName is "default", "ashmem", etc.
 // If it starts with "android.hidl.", a static map is looked up instead.
-vintf::Transport getTransport(const std::string &name);
+vintf::Transport getTransport(const std::string &interfaceName,
+                              const std::string &instanceName);
 
 // hidl_death_recipient is a callback interfaced that can be used with
 // linkToDeath() / unlinkToDeath()
@@ -234,7 +236,23 @@
         return *this;
     }
 
-    // TODO move constructor/move assignment
+    // move constructor
+    hidl_memory(hidl_memory&& other) {
+        *this = std::move(other);
+    }
+
+    // move assignment
+    hidl_memory &operator=(hidl_memory &&other) {
+        if (this != &other) {
+            mHandle = std::move(other.mHandle);
+            mSize = other.mSize;
+            mName = std::move(other.mName);
+            other.mSize = 0;
+        }
+
+        return *this;
+    }
+
 
     ~hidl_memory() {
     }
diff --git a/manifest.xml b/manifest.xml
new file mode 100644
index 0000000..8d6697b
--- /dev/null
+++ b/manifest.xml
@@ -0,0 +1,31 @@
+<!-- TODO(b/35434793): move to frameworks/interfaces -->
+
+<manifest version="1.0">
+    <hal>
+        <name>android.hidl.manager</name>
+        <transport>hwbinder</transport>
+        <version>1.0</version>
+        <interface>
+            <name>IServiceManager</name>
+            <instance>manager</instance>
+        </interface>
+    </hal>
+    <hal>
+        <name>android.hidl.allocator</name>
+        <transport>hwbinder</transport>
+        <version>1.0</version>
+        <interface>
+            <name>IAllocator</name>
+            <instance>ashmem</instance>
+        </interface>
+    </hal>
+    <hal>
+        <name>android.hidl.memory</name>
+        <transport>passthrough</transport>
+        <version>1.0</version>
+        <interface>
+            <name>IMapper</name>
+            <instance>ashmem</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/test_main.cpp b/test_main.cpp
index 6bd7f83..4f59371 100644
--- a/test_main.cpp
+++ b/test_main.cpp
@@ -61,6 +61,8 @@
     EXPECT_STREQ(s2.c_str(), "s2");
     hidl_string s2a(nullptr); // copy constructor from null cstr
     EXPECT_STREQ("", s2a);
+    s2a = nullptr; // = from nullptr cstr
+    EXPECT_STREQ(s2a.c_str(), "");
     hidl_string s3 = hidl_string("s3"); // move =
     EXPECT_STREQ(s3.c_str(), "s3");
     hidl_string s4 = hidl_string("12345", 3); // copy constructor from cstr w/ length
diff --git a/transport/LegacySupport.cpp b/transport/LegacySupport.cpp
index 17371d4..95796bf 100644
--- a/transport/LegacySupport.cpp
+++ b/transport/LegacySupport.cpp
@@ -15,36 +15,39 @@
  */
 #define LOG_TAG "libhidltransport"
 
+#include <inttypes.h>
+
 #include <hidl/LegacySupport.h>
 
 #include <chrono>
-#include <cutils/properties.h>
 #include <thread>
 #include <utils/misc.h>
 #include <utils/Log.h>
+#include <utils/SystemClock.h>
+
+#include <android-base/properties.h>
 
 namespace android {
 namespace hardware {
 
-static const char* kDataProperty = "vold.post_fs_data_done";
-
-void waitForData() {
-    using namespace std::literals::chrono_literals;
-
-    // TODO(b/34274385) remove this
-    while (!property_get_bool(kDataProperty, false)) {
-        std::this_thread::sleep_for(300ms);
-    }
-
-    // TODO(b/35178781) wait a bit longer
-    std::this_thread::sleep_for(300ms);
-}
-
 namespace details {
 
+using android::base::GetBoolProperty;
+using android::base::GetUintProperty;
+using android::base::WaitForPropertyCreation;
+
+static const char* kPersistPropReadyProperty = "ro.boottime.persistent_properties";
+static const char* kBinderizationProperty = "persist.hal.binderization";
+
 bool blockingHalBinderizationEnabled() {
-    waitForData();
-    return property_get_bool("persist.hal.binderization", false);
+    uint64_t t = GetUintProperty<uint64_t>(kPersistPropReadyProperty, 0, UINT64_MAX);
+    if (t == 0) { // not set yet
+        int64_t startTime = elapsedRealtime();
+        WaitForPropertyCreation(kPersistPropReadyProperty, std::chrono::milliseconds::max());
+        ALOGI("Waiting for %s took %" PRId64 " ms", kPersistPropReadyProperty,
+              elapsedRealtime() - startTime);
+    }
+    return GetBoolProperty(kBinderizationProperty, false);
 }
 
 void blockIfBinderizationDisabled(const std::string& interface,
@@ -58,7 +61,7 @@
     std::string package = interface.substr(0, loc);
 
     // only block if this is supposed to be toggled
-    if (getTransport(interface) != vintf::Transport::TOGGLED) {
+    if (getTransport(interface, instance) != vintf::Transport::TOGGLED) {
         return;
     }
 
diff --git a/transport/token/1.0/ITokenManager.hal b/transport/token/1.0/ITokenManager.hal
index 2f0650b..b1bb735 100644
--- a/transport/token/1.0/ITokenManager.hal
+++ b/transport/token/1.0/ITokenManager.hal
@@ -23,9 +23,8 @@
 interface ITokenManager {
 
     /**
-     * Register an interface. The server must only keep a weak reference
-     * to the token. The lifetime of the token is thus linked to the
-     * lifetime of the stored interface.
+     * Register an interface. The server must keep a strong reference
+     * to the interface until the token is destroyed by calling unregister.
      *
      * @param store Interface which can later be fetched with the returned token.
      * @return token Opaque value which may be used as inputs to other functions.
@@ -33,20 +32,17 @@
     createToken(interface store) generates (uint64_t token);
 
     /**
-     * Explicitly unregister an interface. If the server still holds a weak reference
-     * to an interface, but that interface interface is deleted and the reference
-     * cannot be promoted, then success must be false.
+     * Destory a token and the strong reference to the associated interface.
      *
-     * @param token Token recieved from createToken
-     * @return success Whether or not an interface was successfully unregistered.
+     * @param token Token received from createToken
+     * @return success Whether or not the token was successfully unregistered.
      */
     unregister(uint64_t token) generates (bool success);
 
     /**
-     * Fetches an interface from a provided token. This must also unregister the
-     * token.
+     * Fetch an interface from a provided token.
      *
-     * @param token Token recieved from createToken
+     * @param token Token received from createToken
      * @return store Interface registered with createToken and the corresponding
      *               token or nullptr.
      */