Merge "binderRpcTest: named normal modes"
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index eadf678..bec262e 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -223,8 +223,13 @@
 #endif  // !VENDORSERVICEMANAGER
 
 ServiceManager::Service::~Service() {
-    if (!hasClients) {
-        // only expected to happen on process death
+    if (hasClients) {
+        // only expected to happen on process death, we don't store the service
+        // name this late (it's in the map that holds this service), but if it
+        // is happening, we might want to change 'unlinkToDeath' to explicitly
+        // clear this bit so that we can abort in other cases, where it would
+        // mean inconsistent logic in servicemanager (unexpected and tested, but
+        // the original lazy service impl here had that bug).
         LOG(WARNING) << "a service was removed when there are clients";
     }
 }
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index 1a821f1..233a8e4 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -90,16 +90,16 @@
     return mMaxIncomingThreads;
 }
 
-void RpcSession::setMaxOutgoingConnections(size_t threads) {
+void RpcSession::setMaxOutgoingConnections(size_t connections) {
     RpcMutexLockGuard _l(mMutex);
     LOG_ALWAYS_FATAL_IF(mStartedSetup,
                         "Must set max outgoing threads before setting up connections");
-    mMaxOutgoingThreads = threads;
+    mMaxOutgoingConnections = connections;
 }
 
 size_t RpcSession::getMaxOutgoingThreads() {
     RpcMutexLockGuard _l(mMutex);
-    return mMaxOutgoingThreads;
+    return mMaxOutgoingConnections;
 }
 
 bool RpcSession::setProtocolVersionInternal(uint32_t version, bool checkStarted) {
@@ -558,11 +558,11 @@
         return status;
     }
 
-    size_t outgoingThreads = std::min(numThreadsAvailable, mMaxOutgoingThreads);
-    ALOGI_IF(outgoingThreads != numThreadsAvailable,
+    size_t outgoingConnections = std::min(numThreadsAvailable, mMaxOutgoingConnections);
+    ALOGI_IF(outgoingConnections != numThreadsAvailable,
              "Server hints client to start %zu outgoing threads, but client will only start %zu "
              "because it is preconfigured to start at most %zu outgoing threads.",
-             numThreadsAvailable, outgoingThreads, mMaxOutgoingThreads);
+             numThreadsAvailable, outgoingConnections, mMaxOutgoingConnections);
 
     // TODO(b/189955605): we should add additional sessions dynamically
     // instead of all at once - the other side should be responsible for setting
@@ -571,10 +571,10 @@
     // any requests at all.
 
     // we've already setup one client
-    LOG_RPC_DETAIL("RpcSession::setupClient() instantiating %zu outgoing (server max: %zu) and %zu "
-                   "incoming threads",
-                   outgoingThreads, numThreadsAvailable, mMaxIncomingThreads);
-    for (size_t i = 0; i + 1 < outgoingThreads; i++) {
+    LOG_RPC_DETAIL("RpcSession::setupClient() instantiating %zu outgoing connections (server max: "
+                   "%zu) and %zu incoming threads",
+                   outgoingConnections, numThreadsAvailable, mMaxIncomingThreads);
+    for (size_t i = 0; i + 1 < outgoingConnections; i++) {
         if (status_t status = connectAndInit(mId, false /*incoming*/); status != OK) return status;
     }
 
diff --git a/libs/binder/include/binder/RpcSession.h b/libs/binder/include/binder/RpcSession.h
index e301569..0750ccf 100644
--- a/libs/binder/include/binder/RpcSession.h
+++ b/libs/binder/include/binder/RpcSession.h
@@ -54,8 +54,6 @@
  */
 class RpcSession final : public virtual RefBase {
 public:
-    static constexpr size_t kDefaultMaxOutgoingThreads = 10;
-
     // Create an RpcSession with default configuration (raw sockets).
     static sp<RpcSession> make();
 
@@ -80,8 +78,8 @@
 
     /**
      * Set the maximum number of outgoing connections allowed to be made.
-     * By default, this is |kDefaultMaxOutgoingThreads|. This must be called before setting up this
-     * connection as a client.
+     * By default, this is |kDefaultMaxOutgoingConnections|. This must be called before setting up
+     * this connection as a client.
      *
      * For an RpcSession client, if you are connecting to a server which starts N threads,
      * then this must be set to >= N. If you set the maximum number of outgoing connections
@@ -90,7 +88,7 @@
      * created. This API is used to limit the amount of resources a server can request you
      * create.
      */
-    void setMaxOutgoingConnections(size_t threads);
+    void setMaxOutgoingConnections(size_t connections);
     size_t getMaxOutgoingThreads();
 
     /**
@@ -223,6 +221,8 @@
     friend RpcState;
     explicit RpcSession(std::unique_ptr<RpcTransportCtx> ctx);
 
+    static constexpr size_t kDefaultMaxOutgoingConnections = 10;
+
     // internal version of setProtocolVersion that
     // optionally skips the mStartedSetup check
     [[nodiscard]] bool setProtocolVersionInternal(uint32_t version, bool checkStarted);
@@ -372,7 +372,7 @@
 
     bool mStartedSetup = false;
     size_t mMaxIncomingThreads = 0;
-    size_t mMaxOutgoingThreads = kDefaultMaxOutgoingThreads;
+    size_t mMaxOutgoingConnections = kDefaultMaxOutgoingConnections;
     std::optional<uint32_t> mProtocolVersion;
     FileDescriptorTransportMode mFileDescriptorTransportMode = FileDescriptorTransportMode::NONE;
 
diff --git a/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp b/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp
index e273dff..a157792 100644
--- a/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp
+++ b/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp
@@ -130,7 +130,7 @@
 void ARpcSession_setMaxIncomingThreads(ARpcSession* session, size_t threads);
 
 // Sets the maximum number of outgoing connections.
-void ARpcSession_setMaxOutgoingConnections(ARpcSession* session, size_t threads);
+void ARpcSession_setMaxOutgoingConnections(ARpcSession* session, size_t connections);
 
 // Decrements the refcount of the underlying RpcSession object.
 void ARpcSession_free(ARpcSession* session);
diff --git a/libs/binder/libbinder_rpc_unstable.cpp b/libs/binder/libbinder_rpc_unstable.cpp
index 971b3a0..a167f23 100644
--- a/libs/binder/libbinder_rpc_unstable.cpp
+++ b/libs/binder/libbinder_rpc_unstable.cpp
@@ -265,8 +265,8 @@
     session->setMaxIncomingThreads(threads);
 }
 
-void ARpcSession_setMaxOutgoingConnections(ARpcSession* handle, size_t threads) {
+void ARpcSession_setMaxOutgoingConnections(ARpcSession* handle, size_t connections) {
     auto session = handleToStrongPointer<RpcSession>(handle);
-    session->setMaxOutgoingConnections(threads);
+    session->setMaxOutgoingConnections(connections);
 }
 }
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel.h b/libs/binder/ndk/include_ndk/android/binder_parcel.h
index f68612c..d833b83 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel.h
@@ -26,11 +26,11 @@
 
 #pragma once
 
+#include <android/binder_status.h>
 #include <stdbool.h>
 #include <stddef.h>
 #include <sys/cdefs.h>
-
-#include <android/binder_status.h>
+#include <uchar.h>
 
 struct AIBinder;
 typedef struct AIBinder AIBinder;
diff --git a/libs/gui/view/Surface.cpp b/libs/gui/view/Surface.cpp
index 1bfe462..198908d 100644
--- a/libs/gui/view/Surface.cpp
+++ b/libs/gui/view/Surface.cpp
@@ -16,17 +16,59 @@
 
 #define LOG_TAG "Surface"
 
-#include <gui/view/Surface.h>
-
+#include <android/binder_libbinder.h>
+#include <android/binder_parcel.h>
+#include <android/native_window.h>
 #include <binder/Parcel.h>
-
-#include <utils/Log.h>
-
 #include <gui/IGraphicBufferProducer.h>
+#include <gui/Surface.h>
+#include <gui/view/Surface.h>
+#include <system/window.h>
+#include <utils/Log.h>
 
 namespace android {
 namespace view {
 
+// Since this is a parcelable utility and we want to keep the wire format stable, only build this
+// when building the system libgui to detect any issues loading the wrong libgui from
+// libnativewindow
+
+#if (!defined(__ANDROID_APEX__) && !defined(__ANDROID_VNDK__))
+
+extern "C" status_t android_view_Surface_writeToParcel(ANativeWindow* _Nonnull window,
+                                                       Parcel* _Nonnull parcel) {
+    int value;
+    int err = (*window->query)(window, NATIVE_WINDOW_CONCRETE_TYPE, &value);
+    if (err != OK || value != NATIVE_WINDOW_SURFACE) {
+        ALOGE("Error: ANativeWindow is not backed by Surface");
+        return STATUS_BAD_VALUE;
+    }
+    // Use a android::view::Surface to parcelize the window
+    android::view::Surface shimSurface;
+    shimSurface.graphicBufferProducer = android::Surface::getIGraphicBufferProducer(window);
+    shimSurface.surfaceControlHandle = android::Surface::getSurfaceControlHandle(window);
+    return shimSurface.writeToParcel(parcel);
+}
+
+extern "C" status_t android_view_Surface_readFromParcel(
+        const Parcel* _Nonnull parcel, ANativeWindow* _Nullable* _Nonnull outWindow) {
+    // Use a android::view::Surface to unparcel the window
+    android::view::Surface shimSurface;
+    status_t ret = shimSurface.readFromParcel(parcel);
+    if (ret != OK) {
+        ALOGE("%s: Error: Failed to create android::view::Surface from AParcel", __FUNCTION__);
+        return STATUS_BAD_VALUE;
+    }
+    auto surface = sp<android::Surface>::make(shimSurface.graphicBufferProducer, false,
+                                              shimSurface.surfaceControlHandle);
+    ANativeWindow* anw = surface.get();
+    ANativeWindow_acquire(anw);
+    *outWindow = anw;
+    return STATUS_OK;
+}
+
+#endif
+
 status_t Surface::writeToParcel(Parcel* parcel) const {
     return writeToParcel(parcel, false);
 }
diff --git a/libs/nativewindow/ANativeWindow.cpp b/libs/nativewindow/ANativeWindow.cpp
index 3762e66..73a05fc 100644
--- a/libs/nativewindow/ANativeWindow.cpp
+++ b/libs/nativewindow/ANativeWindow.cpp
@@ -24,14 +24,49 @@
 
 #include <private/android/AHardwareBufferHelpers.h>
 
+#include <android/binder_libbinder.h>
+#include <dlfcn.h>
 #include <log/log.h>
 #include <ui/GraphicBuffer.h>
-#include <gui/Surface.h>
-#include <gui/view/Surface.h>
-#include <android/binder_libbinder.h>
 
 using namespace android;
 
+#if defined(__ANDROID_APEX__) || defined(__ANDROID_VNDK__)
+#error libnativewindow can only be built for system
+#endif
+
+using android_view_Surface_writeToParcel = status_t (*)(ANativeWindow* _Nonnull window,
+                                                        Parcel* _Nonnull parcel);
+
+using android_view_Surface_readFromParcel =
+        status_t (*)(const Parcel* _Nonnull parcel, ANativeWindow* _Nullable* _Nonnull outWindow);
+
+struct SurfaceParcelables {
+    android_view_Surface_writeToParcel write = nullptr;
+    android_view_Surface_readFromParcel read = nullptr;
+};
+
+const SurfaceParcelables* getSurfaceParcelFunctions() {
+    static SurfaceParcelables funcs = []() -> SurfaceParcelables {
+        SurfaceParcelables ret;
+        void* dl = dlopen("libgui.so", RTLD_NOW);
+        LOG_ALWAYS_FATAL_IF(!dl, "Failed to find libgui.so");
+        ret.write =
+                (android_view_Surface_writeToParcel)dlsym(dl, "android_view_Surface_writeToParcel");
+        LOG_ALWAYS_FATAL_IF(!ret.write,
+                            "libgui.so missing android_view_Surface_writeToParcel; "
+                            "loaded wrong libgui?");
+        ret.read =
+                (android_view_Surface_readFromParcel)dlsym(dl,
+                                                           "android_view_Surface_readFromParcel");
+        LOG_ALWAYS_FATAL_IF(!ret.read,
+                            "libgui.so missing android_view_Surface_readFromParcel; "
+                            "loaded wrong libgui?");
+        return ret;
+    }();
+    return &funcs;
+}
+
 static int32_t query(ANativeWindow* window, int what) {
     int value;
     int res = window->query(window, what, &value);
@@ -64,13 +99,6 @@
             return false;
     }
 }
-static sp<IGraphicBufferProducer> IGraphicBufferProducer_from_ANativeWindow(ANativeWindow* window) {
-    return Surface::getIGraphicBufferProducer(window);
-}
-
-static sp<IBinder> SurfaceControlHandle_from_ANativeWindow(ANativeWindow* window) {
-    return Surface::getSurfaceControlHandle(window);
-}
 
 /**************************************************************************************************
  * NDK
@@ -348,38 +376,24 @@
 
 binder_status_t ANativeWindow_readFromParcel(
         const AParcel* _Nonnull parcel, ANativeWindow* _Nullable* _Nonnull outWindow) {
-    const Parcel* nativeParcel = AParcel_viewPlatformParcel(parcel);
-
-    // Use a android::view::Surface to unparcel the window
-    std::shared_ptr<android::view::Surface> shimSurface = std::shared_ptr<android::view::Surface>();
-    status_t ret = shimSurface->readFromParcel(nativeParcel);
-    if (ret != OK) {
-        ALOGE("%s: Error: Failed to create android::view::Surface from AParcel", __FUNCTION__);
-        return STATUS_BAD_VALUE;
+    auto funcs = getSurfaceParcelFunctions();
+    if (funcs->read == nullptr) {
+        ALOGE("Failed to load Surface_readFromParcel implementation");
+        return STATUS_FAILED_TRANSACTION;
     }
-    sp<Surface> surface = sp<Surface>::make(
-            shimSurface->graphicBufferProducer, false, shimSurface->surfaceControlHandle);
-    ANativeWindow* anw = surface.get();
-    ANativeWindow_acquire(anw);
-    *outWindow = anw;
-    return STATUS_OK;
+    const Parcel* nativeParcel = AParcel_viewPlatformParcel(parcel);
+    return funcs->read(nativeParcel, outWindow);
 }
 
 binder_status_t ANativeWindow_writeToParcel(
         ANativeWindow* _Nonnull window, AParcel* _Nonnull parcel) {
-    int value;
-    int err = (*window->query)(window, NATIVE_WINDOW_CONCRETE_TYPE, &value);
-    if (err != OK || value != NATIVE_WINDOW_SURFACE) {
-        ALOGE("Error: ANativeWindow is not backed by Surface");
-        return STATUS_BAD_VALUE;
+    auto funcs = getSurfaceParcelFunctions();
+    if (funcs->write == nullptr) {
+        ALOGE("Failed to load Surface_writeToParcel implementation");
+        return STATUS_FAILED_TRANSACTION;
     }
-    // Use a android::view::Surface to parcelize the window
-    std::shared_ptr<android::view::Surface> shimSurface = std::shared_ptr<android::view::Surface>();
-    shimSurface->graphicBufferProducer = IGraphicBufferProducer_from_ANativeWindow(window);
-    shimSurface->surfaceControlHandle = SurfaceControlHandle_from_ANativeWindow(window);
-
     Parcel* nativeParcel = AParcel_viewPlatformParcel(parcel);
-    return shimSurface->writeToParcel(nativeParcel);
+    return funcs->write(window, nativeParcel);
 }
 
 /**************************************************************************************************