DO NOT MERGE - Merge pi-dev@5234907 into stage-aosp-master

Bug: 120848293
Change-Id: I6438d671542f23e262a4327fa48601bee221f494
diff --git a/.clang-format b/.clang-format
deleted file mode 100644
index 3494682..0000000
--- a/.clang-format
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# Copyright (C) 2017 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.
-#
-
-BasedOnStyle: Google
-CommentPragmas: NOLINT:.*
-DerivePointerAlignment: false
-AllowShortFunctionsOnASingleLine: Inline
-ColumnLimit: 100
-TabWidth: 4
-UseTab: Never
-IndentWidth: 4
-ContinuationIndentWidth: 8
diff --git a/.clang-format b/.clang-format
new file mode 120000
index 0000000..ddcf5a2
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1 @@
+../../build/soong/scripts/system-clang-format
\ No newline at end of file
diff --git a/base/include/hidl/HidlSupport.h b/base/include/hidl/HidlSupport.h
index 43e84c0..55f21ea 100644
--- a/base/include/hidl/HidlSupport.h
+++ b/base/include/hidl/HidlSupport.h
@@ -345,19 +345,7 @@
         *this = std::move(other);
     }
 
-    hidl_vec(const std::initializer_list<T> list)
-            : mOwnsBuffer(true) {
-        if (list.size() > UINT32_MAX) {
-            details::logAlwaysFatal("hidl_vec can't hold more than 2^32 elements.");
-        }
-        mSize = static_cast<uint32_t>(list.size());
-        mBuffer = new T[mSize];
-
-        size_t idx = 0;
-        for (auto it = list.begin(); it != list.end(); ++it) {
-            mBuffer[idx++] = *it;
-        }
-    }
+    hidl_vec(const std::initializer_list<T> list) : hidl_vec() { *this = list; }
 
     hidl_vec(const std::vector<T> &other) : hidl_vec() {
         *this = other;
@@ -453,6 +441,24 @@
         return *this;
     }
 
+    hidl_vec& operator=(const std::initializer_list<T> list) {
+        if (list.size() > UINT32_MAX) {
+            details::logAlwaysFatal("hidl_vec can't hold more than 2^32 elements.");
+        }
+        if (mOwnsBuffer) {
+            delete[] mBuffer;
+        }
+        mSize = static_cast<uint32_t>(list.size());
+        mBuffer = new T[mSize];
+        mOwnsBuffer = true;
+
+        size_t idx = 0;
+        for (auto it = list.begin(); it != list.end(); ++it) {
+            mBuffer[idx++] = *it;
+        }
+        return *this;
+    }
+
     // cast to an std::vector.
     operator std::vector<T>() const {
         std::vector<T> v(mSize);
diff --git a/test_main.cpp b/test_main.cpp
index beb89d7..2b9f52c 100644
--- a/test_main.cpp
+++ b/test_main.cpp
@@ -280,6 +280,21 @@
     EXPECT_TRUE(hv1 != hv3);
 }
 
+TEST_F(LibHidlTest, VecEqInitializerTest) {
+    std::vector<int32_t> reference{5, 6, 7};
+    android::hardware::hidl_vec<int32_t> hv1{1, 2, 3};
+    hv1 = {5, 6, 7};
+    android::hardware::hidl_vec<int32_t> hv2;
+    hv2 = {5, 6, 7};
+    android::hardware::hidl_vec<int32_t> hv3;
+    hv3 = {5, 6, 8};
+
+    // use the == and != operator intentionally here
+    EXPECT_TRUE(hv1 == hv2);
+    EXPECT_TRUE(hv1 == reference);
+    EXPECT_TRUE(hv1 != hv3);
+}
+
 TEST_F(LibHidlTest, VecRangeCtorTest) {
     struct ConvertibleType {
         int val;
diff --git a/transport/HidlLazyUtils.cpp b/transport/HidlLazyUtils.cpp
index 9223af6..8e3fdf3 100644
--- a/transport/HidlLazyUtils.cpp
+++ b/transport/HidlLazyUtils.cpp
@@ -26,26 +26,42 @@
 namespace hardware {
 namespace details {
 
+using ::android::hidl::base::V1_0::IBase;
+
 class ClientCounterCallback : public ::android::hidl::manager::V1_2::IClientCallback {
    public:
-    ClientCounterCallback() : mNumConnectedServices(0), mNumRegisteredServices(0) {}
+    ClientCounterCallback() : mNumConnectedServices(0) {}
 
-    void incServiceCounter();
+    bool addRegisteredService(const sp<IBase>& service, const std::string& name);
 
    protected:
-    Return<void> onClients(const sp<::android::hidl::base::V1_0::IBase>& service,
-                           bool clients) override;
+    Return<void> onClients(const sp<IBase>& service, bool clients) override;
 
    private:
     /**
+     * Registers or re-registers services. Returns whether successful.
+     */
+    bool registerService(const sp<IBase>& service, const std::string& name);
+
+    /**
+     * Unregisters all services that we can. If we can't unregister all, re-register other
+     * services.
+     */
+    void tryShutdown();
+
+    /**
      * Counter of the number of services that currently have at least one client.
      */
     size_t mNumConnectedServices;
 
+    struct Service {
+        sp<IBase> service;
+        std::string name;
+    };
     /**
      * Number of services that have been registered.
      */
-    size_t mNumRegisteredServices;
+    std::vector<Service> mRegisteredServices;
 };
 
 class LazyServiceRegistrarImpl {
@@ -59,8 +75,37 @@
     sp<ClientCounterCallback> mClientCallback;
 };
 
-void ClientCounterCallback::incServiceCounter() {
-    mNumRegisteredServices++;
+bool ClientCounterCallback::addRegisteredService(const sp<IBase>& service,
+                                                 const std::string& name) {
+    bool success = registerService(service, name);
+
+    if (success) {
+        mRegisteredServices.push_back({service, name});
+    }
+
+    return success;
+}
+
+bool ClientCounterCallback::registerService(const sp<IBase>& service, const std::string& name) {
+    auto manager = hardware::defaultServiceManager1_2();
+
+    const std::string descriptor = getDescriptor(service.get());
+
+    LOG(INFO) << "Registering HAL: " << descriptor << " with name: " << name;
+
+    status_t res = android::hardware::details::registerAsServiceInternal(service, name);
+    if (res != android::OK) {
+        LOG(ERROR) << "Failed to register as service.";
+        return false;
+    }
+
+    bool ret = manager->registerClientCallback(getDescriptor(service.get()), name, service, this);
+    if (!ret) {
+        LOG(ERROR) << "Failed to add client callback.";
+        return false;
+    }
+
+    return true;
 }
 
 /**
@@ -70,38 +115,64 @@
 Return<void> ClientCounterCallback::onClients(const sp<::android::hidl::base::V1_0::IBase>& service,
                                               bool clients) {
     if (clients) {
-        LOG(INFO) << "HAL " << service->descriptor << " connected.";
         mNumConnectedServices++;
     } else {
-        LOG(INFO) << "HAL " << service->descriptor << " disconnected.";
         mNumConnectedServices--;
     }
-    LOG(INFO) << "HAL has " << mNumConnectedServices << " (of " << mNumRegisteredServices
-              << " available) clients in use.";
+
+    LOG(INFO) << "Process has " << mNumConnectedServices << " (of " << mRegisteredServices.size()
+              << " available) client(s) in use after notification " << getDescriptor(service.get())
+              << " has clients: " << clients;
 
     if (mNumConnectedServices == 0) {
-        LOG(INFO) << "Exiting HAL. No clients in use for any service in process.";
+        tryShutdown();
+    }
+
+    return Status::ok();
+}
+
+void ClientCounterCallback::tryShutdown() {
+    LOG(INFO) << "Trying to exit HAL. No clients in use for any service in process.";
+
+    auto manager = hardware::defaultServiceManager1_2();
+
+    auto unRegisterIt = mRegisteredServices.begin();
+    for (; unRegisterIt != mRegisteredServices.end(); ++unRegisterIt) {
+        auto& entry = (*unRegisterIt);
+
+        const std::string descriptor = getDescriptor(entry.service.get());
+        bool success = manager->tryUnregister(descriptor, entry.name, entry.service);
+
+        if (!success) {
+            LOG(INFO) << "Failed to unregister HAL " << descriptor << "/" << entry.name;
+            break;
+        }
+    }
+
+    if (unRegisterIt == mRegisteredServices.end()) {
+        LOG(INFO) << "Unregistered all clients and exiting";
         exit(EXIT_SUCCESS);
     }
-    return Status::ok();
+
+    for (auto reRegisterIt = mRegisteredServices.begin(); reRegisterIt != unRegisterIt;
+         reRegisterIt++) {
+        auto& entry = (*reRegisterIt);
+
+        // re-register entry
+        if (!registerService(entry.service, entry.name)) {
+            // Must restart. Otherwise, clients will never be able to get ahold of this service.
+            LOG(FATAL) << "Bad state: could not re-register " << getDescriptor(entry.service.get());
+        }
+    }
 }
 
 status_t LazyServiceRegistrarImpl::registerService(
     const sp<::android::hidl::base::V1_0::IBase>& service, const std::string& name) {
-    static auto manager = hardware::defaultServiceManager1_2();
-    LOG(INFO) << "Registering HAL: " << service->descriptor << " with name: " << name;
-    status_t res = android::hardware::details::registerAsServiceInternal(service, name);
-    if (res == android::OK) {
-        mClientCallback->incServiceCounter();
-        bool ret = manager->registerClientCallback(service, mClientCallback);
-        if (!ret) {
-            res = android::INVALID_OPERATION;
-            LOG(ERROR) << "Failed to add client callback";
-        }
-    } else {
-        LOG(ERROR) << "Failed to register as service";
+    if (!mClientCallback->addRegisteredService(service, name)) {
+        return ::android::UNKNOWN_ERROR;
     }
-    return res;
+
+    return ::android::OK;
 }
 
 }  // namespace details
diff --git a/transport/HidlTransportUtils.cpp b/transport/HidlTransportUtils.cpp
index 4e952eb..8c61281 100644
--- a/transport/HidlTransportUtils.cpp
+++ b/transport/HidlTransportUtils.cpp
@@ -56,6 +56,10 @@
 }
 
 std::string getDescriptor(IBase* interface) {
+    if (interface == nullptr) {
+        return "";
+    }
+
     std::string myDescriptor{};
     auto ret = interface->interfaceDescriptor([&](const hidl_string &types) {
         myDescriptor = types.c_str();
diff --git a/transport/allocator/1.0/utils/Android.bp b/transport/allocator/1.0/utils/Android.bp
index b1a3f41..9f70963 100644
--- a/transport/allocator/1.0/utils/Android.bp
+++ b/transport/allocator/1.0/utils/Android.bp
@@ -18,6 +18,7 @@
     vndk: {
         enabled: true,
     },
+    double_loadable: true,
     defaults: ["libhidl-defaults"],
     shared_libs: [
         "libbinder",
diff --git a/transport/current.txt b/transport/current.txt
index 322857a..2abf6f7 100644
--- a/transport/current.txt
+++ b/transport/current.txt
@@ -26,3 +26,8 @@
 
 # Clarification for b/67503915
 ec7fd79ed02dfa85bc499426adae3ebe23ef0524f3cd6957139324b83b18ca4c android.hidl.base@1.0::IBase
+
+# HALs released in Android Q
+a570fd436aed5eeeea2495b9267e7f9c4808d51efd4c9ba0913b9102eb93aeed android.hidl.manager@1.2::IClientCallback
+6f3a8a3fd4bfbd02e4e61c732d2df616ff69434a1ed83cda337303adc6d714df android.hidl.manager@1.2::IServiceManager
+b1c4fbdebe6d0def9b4f63aa83a0641f694fd5732ad32881a57fe12d5310a259 android.hidl.safe_union@1.0::types
diff --git a/transport/manager/1.2/IClientCallback.hal b/transport/manager/1.2/IClientCallback.hal
index 1189e44..8ebb044 100644
--- a/transport/manager/1.2/IClientCallback.hal
+++ b/transport/manager/1.2/IClientCallback.hal
@@ -21,6 +21,10 @@
      * This is called when there is a transition between having >= 1 clients and having 0 clients
      * (or vice versa).
      *
+     * Upon receiving hasClients false, if the process decides to exit, it is recommended to try to
+     * unregister using @1.2::IServiceManager's tryUnregister before quiting in case another client
+     * associates.
+     *
      * @param registered binder 'server' registered with IServiceManager's registerClientCallback
      * @param hasClients whether there are currently clients
      *     true - when there are >= 1 clients. This must be called as soon as IServiceManager::get
diff --git a/transport/manager/1.2/IServiceManager.hal b/transport/manager/1.2/IServiceManager.hal
index e1629d6..d79403d 100644
--- a/transport/manager/1.2/IServiceManager.hal
+++ b/transport/manager/1.2/IServiceManager.hal
@@ -27,7 +27,9 @@
      * If the service has clients at the time of registration, the callback is called with
      * hasClients true. After that, it is called based on the changes in clientele.
      *
-     * @param server non-null service waiting to have no clients
+     * @param fqName Fully-qualified interface name (used to register)
+     * @param name Instance name (of the registered service)
+     * @param server non-null service waiting to have no clients (previously registered)
      * @param cb non-null callback to call when there are no clients
      * @return success
      *     true on success
@@ -35,7 +37,11 @@
      *      - the server or cb parameters are null
      *      - this is called by a process other than the server process
      */
-    registerClientCallback(interface server, IClientCallback cb) generates (bool success);
+    registerClientCallback(string fqName,
+                           string name,
+                           interface server,
+                           IClientCallback cb)
+        generates (bool success);
 
     /**
      * Removes a callback previously registered with registerClientCallback.
@@ -68,9 +74,32 @@
      *
      * See also @1.0::IServiceManager's listByInterface function.
      *
-     * @param fqName         Fully-qualified interface name.
+     * @param fqName Fully-qualified interface name.
      *
      * @return instanceNames List of instance names running the particular service.
      */
     listManifestByInterface(string fqName) generates (vec<string> instanceNames);
+
+    /**
+     * Unregisters a service if there are no clients for it. This must only unregister the
+     * service if it is called from the same process that registered the service.
+     *
+     * This unregisters all instances of the service, even if they are under a different instance
+     * name.
+     *
+     * Recommended usage is when creating a lazy process, try unregistering when IClientCallback's
+     * onClients(*, false) is called. If this unregister is successful, then it is safe to exit. If
+     * it is unsuccessful, then you can assume a client re-associated with the server. If a process
+     * has multiple servers, and only some succeed in unregistration, then the unregistered services
+     * can be re-registered.
+     *
+     * See also addWithChain and @1.0::IServiceManager's add.
+     *
+     * @param fqName Fully-qualified interface name.
+     * @param name Instance name.
+     * @param service Handle to registering service.
+     *
+     * @return success Whether the service was successfully unregistered.
+     */
+    tryUnregister(string fqName, string name, interface service) generates (bool success);
 };