Add gServiceSidMap.

Like gServicePrioMap. b/122472540 is filed to merge these maps
in the future, but creating a separate map so that it can be easily
backported.

Bug: 121035042
Test: boot and check for SID values for calls into hwservicemanager
    coming from clients which called IServiceManager::getService.

Change-Id: I4e5821d91ea694f86911218c23e68fcb987daaf9
Merged-In: I4e5821d91ea694f86911218c23e68fcb987daaf9
(cherry picked from commit d7f8d2226f5c7e98d12137732846e4ba55048927)
diff --git a/transport/HidlTransportSupport.cpp b/transport/HidlTransportSupport.cpp
index d0871f6..c3a3031 100644
--- a/transport/HidlTransportSupport.cpp
+++ b/transport/HidlTransportSupport.cpp
@@ -38,6 +38,22 @@
     return handleBinderPoll();
 }
 
+// TODO(b/122472540): only store one data item per object
+template <typename V>
+static void pruneMapLocked(ConcurrentMap<wp<::android::hidl::base::V1_0::IBase>, V>& map) {
+    using ::android::hidl::base::V1_0::IBase;
+
+    std::vector<wp<IBase>> toDelete;
+    for (const auto& kv : map) {
+        if (kv.first.promote() == nullptr) {
+            toDelete.push_back(kv.first);
+        }
+    }
+    for (const auto& k : toDelete) {
+        map.eraseLocked(k);
+    }
+}
+
 bool setMinSchedulerPolicy(const sp<::android::hidl::base::V1_0::IBase>& service,
                            int policy, int priority) {
     if (service->isRemote()) {
@@ -63,6 +79,22 @@
     return true;
 }
 
+bool setRequestingSid(const sp<::android::hidl::base::V1_0::IBase>& service, bool requesting) {
+    if (service->isRemote()) {
+        ALOGE("Can't set requesting sid on remote service.");
+        return false;
+    }
+
+    // Due to ABI considerations, IBase cannot have a destructor to clean this up.
+    // So, because this API is so infrequently used, (expected to be usually only
+    // one time for a process, but it can be more), we are cleaning it up here.
+    std::unique_lock<std::mutex> lock = details::gServiceSidMap.lock();
+    pruneMapLocked(details::gServiceSidMap);
+    details::gServiceSidMap.setLocked(service, requesting);
+
+    return true;
+}
+
 namespace details {
 int32_t getPidIfSharable() {
 #if LIBHIDL_TARGET_DEBUGGABLE
diff --git a/transport/Static.cpp b/transport/Static.cpp
index cbe6add..a506644 100644
--- a/transport/Static.cpp
+++ b/transport/Static.cpp
@@ -35,7 +35,9 @@
 ConcurrentMap<const ::android::hidl::base::V1_0::IBase*, wp<::android::hardware::BHwBinder>>
     gBnMap{};
 
+// TODO(b/122472540): replace with single, hidden map
 ConcurrentMap<wp<::android::hidl::base::V1_0::IBase>, SchedPrio> gServicePrioMap{};
+ConcurrentMap<wp<::android::hidl::base::V1_0::IBase>, bool> gServiceSidMap{};
 
 // Deprecated; kept for ABI compatibility. Use getBsConstructorMap.
 BsConstructorMap gBsConstructorMap{};
diff --git a/transport/include/hidl/ConcurrentMap.h b/transport/include/hidl/ConcurrentMap.h
index 4066869..1b06dfd 100644
--- a/transport/include/hidl/ConcurrentMap.h
+++ b/transport/include/hidl/ConcurrentMap.h
@@ -67,6 +67,7 @@
     std::unique_lock<std::mutex> lock() { return std::unique_lock<std::mutex>(mMutex); }
 
     void setLocked(K&& k, V&& v) { mMap[std::forward<K>(k)] = std::forward<V>(v); }
+    void setLocked(K&& k, const V& v) { mMap[std::forward<K>(k)] = v; }
 
     const V& getLocked(const K& k, const V& def) const {
         const_iterator iter = mMap.find(k);
@@ -76,6 +77,14 @@
         return iter->second;
     }
 
+    size_type eraseLocked(const K& k) { return mMap.erase(k); }
+
+    // the concurrent map must be locked in order to iterate over it
+    iterator begin() { return mMap.begin(); }
+    iterator end() { return mMap.end(); }
+    const_iterator begin() const { return mMap.begin(); }
+    const_iterator end() const { return mMap.end(); }
+
    private:
     mutable std::mutex mMutex;
     std::map<K, V> mMap;
diff --git a/transport/include/hidl/HidlTransportSupport.h b/transport/include/hidl/HidlTransportSupport.h
index 368c2c5..cdcb03e 100644
--- a/transport/include/hidl/HidlTransportSupport.h
+++ b/transport/include/hidl/HidlTransportSupport.h
@@ -96,6 +96,18 @@
     return toBinder<ILeft>(left) == toBinder<IRight>(right);
 }
 
+/**
+ * Sets whether or not this object should request security contexts to be populatd for incoming
+ * calls (e.g. with getCallingSid).
+ *
+ * This method MUST be called before passing this service to another process
+ * and/or registering it with registerAsService().
+ *
+ * @param service the service to set the policy for
+ * @param requesting whether or not to request sid (default is false)
+ */
+bool setRequestingSid(const sp<::android::hidl::base::V1_0::IBase>& service, bool requesting);
+
 namespace details {
 
 // Return PID on userdebug / eng builds and IServiceManager::PidConstant::NO_PID on user builds.
diff --git a/transport/include/hidl/Static.h b/transport/include/hidl/Static.h
index 0522e44..b15be68 100644
--- a/transport/include/hidl/Static.h
+++ b/transport/include/hidl/Static.h
@@ -35,6 +35,7 @@
 };
 
 extern ConcurrentMap<wp<::android::hidl::base::V1_0::IBase>, SchedPrio> gServicePrioMap;
+extern ConcurrentMap<wp<::android::hidl::base::V1_0::IBase>, bool> gServiceSidMap;
 
 // For HidlBinderSupport and autogenerated code
 extern ConcurrentMap<const ::android::hidl::base::V1_0::IBase*, wp<::android::hardware::BHwBinder>>