Merge "Status: don't ignore status in writeToParcel"
diff --git a/include/powermanager/IPowerManager.h b/include/powermanager/IPowerManager.h
index 853f0c9..964e318 100644
--- a/include/powermanager/IPowerManager.h
+++ b/include/powermanager/IPowerManager.h
@@ -46,10 +46,10 @@
         IS_POWER_SAVE_MODE           = IBinder::FIRST_CALL_TRANSACTION + 12,
         GET_POWER_SAVE_STATE         = IBinder::FIRST_CALL_TRANSACTION + 13,
         SET_POWER_SAVE_MODE_ENABLED  = IBinder::FIRST_CALL_TRANSACTION + 14,
-        REBOOT                       = IBinder::FIRST_CALL_TRANSACTION + 17,
-        REBOOT_SAFE_MODE             = IBinder::FIRST_CALL_TRANSACTION + 18,
-        SHUTDOWN                     = IBinder::FIRST_CALL_TRANSACTION + 19,
-        CRASH                        = IBinder::FIRST_CALL_TRANSACTION + 20,
+        REBOOT                       = IBinder::FIRST_CALL_TRANSACTION + 21,
+        REBOOT_SAFE_MODE             = IBinder::FIRST_CALL_TRANSACTION + 22,
+        SHUTDOWN                     = IBinder::FIRST_CALL_TRANSACTION + 23,
+        CRASH                        = IBinder::FIRST_CALL_TRANSACTION + 24,
     };
 
     DECLARE_META_INTERFACE(PowerManager)
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 6023f92..bc541f4 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -73,9 +73,9 @@
     // or dessert updates. Instead, apex users should use libbinder_ndk.
     apex_available: [
         "//apex_available:platform",
-        // TODO(b/139016109) remove these
-        "com.android.media",
+        // TODO(b/139016109) remove these three
         "com.android.media.swcodec",
+        "test_com.android.media.swcodec",
     ],
 
     srcs: [
diff --git a/libs/binder/LazyServiceRegistrar.cpp b/libs/binder/LazyServiceRegistrar.cpp
index d4f26a1..325e204 100644
--- a/libs/binder/LazyServiceRegistrar.cpp
+++ b/libs/binder/LazyServiceRegistrar.cpp
@@ -45,25 +45,31 @@
     Status onClients(const sp<IBinder>& service, bool clients) override;
 
 private:
+    struct Service {
+        sp<IBinder> service;
+        bool allowIsolated;
+        int dumpFlags;
+
+        // whether, based on onClients calls, we know we have a client for this
+        // service or not
+        bool clients = false;
+    };
+
+    /**
+     * Looks up a service guaranteed to be registered (service from onClients).
+     */
+    std::map<std::string, Service>::iterator assertRegisteredService(const sp<IBinder>& service);
+
     /**
      * 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.
-     */
+    // count of services with clients
     size_t mNumConnectedServices;
 
-    struct Service {
-        sp<IBinder> service;
-        bool allowIsolated;
-        int dumpFlags;
-    };
-    /**
-     * Map of registered names and services
-     */
+    // map of registered names and services
     std::map<std::string, Service> mRegisteredServices;
 
     bool mForcePersist;
@@ -82,19 +88,35 @@
         return false;
     }
 
-    if (!manager->registerClientCallback(name, service, this).isOk()) {
-        ALOGE("Failed to add client callback for service %s", name.c_str());
-        return false;
-    }
-
     if (!reRegister) {
+        if (!manager->registerClientCallback(name, service, this).isOk()) {
+            ALOGE("Failed to add client callback for service %s", name.c_str());
+            return false;
+        }
+
         // Only add this when a service is added for the first time, as it is not removed
-        mRegisteredServices[name] = {service, allowIsolated, dumpFlags};
+        mRegisteredServices[name] = {
+              .service = service,
+              .allowIsolated = allowIsolated,
+              .dumpFlags = dumpFlags
+        };
     }
 
     return true;
 }
 
+std::map<std::string, ClientCounterCallback::Service>::iterator ClientCounterCallback::assertRegisteredService(const sp<IBinder>& service) {
+    LOG_ALWAYS_FATAL_IF(service == nullptr, "Got onClients callback for null service");
+    for (auto it = mRegisteredServices.begin(); it != mRegisteredServices.end(); ++it) {
+        auto const& [name, registered] = *it;
+        (void) name;
+        if (registered.service != service) continue;
+        return it;
+    }
+    LOG_ALWAYS_FATAL("Got callback on service which we did not register: %s", String8(service->getInterfaceDescriptor()).c_str());
+    __builtin_unreachable();
+}
+
 void ClientCounterCallback::forcePersist(bool persist) {
     mForcePersist = persist;
     if(!mForcePersist) {
@@ -108,21 +130,25 @@
  * invocations could occur on different threads however.
  */
 Status ClientCounterCallback::onClients(const sp<IBinder>& service, bool clients) {
-    if (clients) {
-        mNumConnectedServices++;
-    } else {
-        mNumConnectedServices--;
+    auto & [name, registered] = *assertRegisteredService(service);
+    if (registered.clients == clients) {
+        LOG_ALWAYS_FATAL("Process already thought %s had clients: %d but servicemanager has "
+                         "notified has clients: %d", name.c_str(), registered.clients, clients);
+    }
+    registered.clients = clients;
+
+    // update cache count of clients
+    {
+         size_t numWithClients = 0;
+         for (const auto& [name, registered] : mRegisteredServices) {
+             (void) name;
+             if (registered.clients) numWithClients++;
+         }
+         mNumConnectedServices = numWithClients;
     }
 
-    // if this fails, we should switch this to keep track of clients inside
-    // of mRegisteredServices so that we know which service is double-counted.
-    LOG_ALWAYS_FATAL_IF(mNumConnectedServices > mRegisteredServices.size(),
-                        "Invalid state: %zu services have clients, but we only know about %zu",
-                        mNumConnectedServices, mRegisteredServices.size());
-
     ALOGI("Process has %zu (of %zu available) client(s) in use after notification %s has clients: %d",
-          mNumConnectedServices, mRegisteredServices.size(),
-          String8(service->getInterfaceDescriptor()).string(), clients);
+          mNumConnectedServices, mRegisteredServices.size(), name.c_str(), clients);
 
     tryShutdown();
     return Status::ok();
@@ -198,4 +224,4 @@
 }
 
 }  // namespace hardware
-}  // namespace android
\ No newline at end of file
+}  // namespace android
diff --git a/libs/binderthreadstate/Android.bp b/libs/binderthreadstate/Android.bp
index 1643fda..c186110 100644
--- a/libs/binderthreadstate/Android.bp
+++ b/libs/binderthreadstate/Android.bp
@@ -20,11 +20,6 @@
     vendor_available: true,
     host_supported: true,
 
-    apex_available: [
-        "//apex_available:platform",
-        "com.android.media",
-    ],
-
     shared_libs: [
         "libbinder",
         "libhidlbase",  // libhwbinder is in here
diff --git a/libs/gui/sysprop/Android.bp b/libs/gui/sysprop/Android.bp
index d107ad6..e7f7c1f 100644
--- a/libs/gui/sysprop/Android.bp
+++ b/libs/gui/sysprop/Android.bp
@@ -1,10 +1,5 @@
 sysprop_library {
     name: "LibGuiProperties",
-    apex_available: [
-        "//apex_available:platform",
-        "com.android.media",
-        "com.android.media.swcodec",
-    ],
     srcs: ["*.sysprop"],
     api_packages: ["android.sysprop"],
     property_owner: "Platform",