Merge "Add snapshotctl_log to bugreport"
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index e61eb6e..d236f76 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -104,12 +104,12 @@
     EXPECT_EQ(-1, validate_apk_path(badint2))
             << badint2 << " should be rejected as a invalid path";
 
-    // Only one subdir should be allowed.
-    const char *bad_path3 = TEST_APP_DIR "example.com/subdir/pkg.apk";
+    // Should not have more than two sub directories
+    const char *bad_path3 = TEST_APP_DIR "random/example.com/subdir/pkg.apk";
     EXPECT_EQ(-1, validate_apk_path(bad_path3))
             << bad_path3 << " should be rejected as a invalid path";
 
-    const char *bad_path4 = TEST_APP_DIR "example.com/subdir/../pkg.apk";
+    const char *bad_path4 = TEST_APP_DIR "random/example.com/subdir/pkg.apk";
     EXPECT_EQ(-1, validate_apk_path(bad_path4))
             << bad_path4 << " should be rejected as a invalid path";
 
@@ -120,6 +120,7 @@
 
 TEST_F(UtilsTest, IsValidApkPath_TopDir) {
     EXPECT_EQ(0, validate_apk_path(TEST_DATA_DIR "app/com.example"));
+    EXPECT_EQ(0, validate_apk_path(TEST_DATA_DIR "app/random/com.example"));
     EXPECT_EQ(0, validate_apk_path(TEST_EXPAND_DIR "app/com.example"));
     EXPECT_EQ(-1, validate_apk_path(TEST_DATA_DIR "data/com.example"));
     EXPECT_EQ(-1, validate_apk_path(TEST_EXPAND_DIR "data/com.example"));
@@ -127,6 +128,7 @@
 
 TEST_F(UtilsTest, IsValidApkPath_TopFile) {
     EXPECT_EQ(0, validate_apk_path(TEST_DATA_DIR "app/com.example/base.apk"));
+    EXPECT_EQ(0, validate_apk_path(TEST_DATA_DIR "app/random/com.example/base.apk"));
     EXPECT_EQ(0, validate_apk_path(TEST_EXPAND_DIR "app/com.example/base.apk"));
     EXPECT_EQ(-1, validate_apk_path(TEST_DATA_DIR "data/com.example/base.apk"));
     EXPECT_EQ(-1, validate_apk_path(TEST_EXPAND_DIR "data/com.example/base.apk"));
@@ -134,6 +136,7 @@
 
 TEST_F(UtilsTest, IsValidApkPath_OatDir) {
     EXPECT_EQ(0, validate_apk_path_subdirs(TEST_DATA_DIR "app/com.example/oat"));
+    EXPECT_EQ(0, validate_apk_path_subdirs(TEST_DATA_DIR "app/random/com.example/oat"));
     EXPECT_EQ(0, validate_apk_path_subdirs(TEST_EXPAND_DIR "app/com.example/oat"));
     EXPECT_EQ(-1, validate_apk_path_subdirs(TEST_DATA_DIR "data/com.example/oat"));
     EXPECT_EQ(-1, validate_apk_path_subdirs(TEST_EXPAND_DIR "data/com.example/oat"));
@@ -141,6 +144,7 @@
 
 TEST_F(UtilsTest, IsValidApkPath_OatDirDir) {
     EXPECT_EQ(0, validate_apk_path_subdirs(TEST_DATA_DIR "app/com.example/oat/arm64"));
+    EXPECT_EQ(0, validate_apk_path_subdirs(TEST_DATA_DIR "app/random/com.example/oat/arm64"));
     EXPECT_EQ(0, validate_apk_path_subdirs(TEST_EXPAND_DIR "app/com.example/oat/arm64"));
     EXPECT_EQ(-1, validate_apk_path_subdirs(TEST_DATA_DIR "data/com.example/oat/arm64"));
     EXPECT_EQ(-1, validate_apk_path_subdirs(TEST_EXPAND_DIR "data/com.example/oat/arm64"));
@@ -148,6 +152,7 @@
 
 TEST_F(UtilsTest, IsValidApkPath_OatDirDirFile) {
     EXPECT_EQ(0, validate_apk_path_subdirs(TEST_DATA_DIR "app/com.example/oat/arm64/base.odex"));
+    EXPECT_EQ(0, validate_apk_path_subdirs(TEST_DATA_DIR "app/random/com.example/oat/arm64/base.odex"));
     EXPECT_EQ(0, validate_apk_path_subdirs(TEST_EXPAND_DIR "app/com.example/oat/arm64/base.odex"));
     EXPECT_EQ(-1, validate_apk_path_subdirs(TEST_DATA_DIR "data/com.example/oat/arm64/base.odex"));
     EXPECT_EQ(-1, validate_apk_path_subdirs(TEST_EXPAND_DIR "data/com.example/oat/arm64/base.odex"));
@@ -164,6 +169,10 @@
     EXPECT_EQ(0, validate_apk_path(path2))
             << path2 << " should be allowed as a valid path";
 
+    const char *path3 = TEST_APP_DIR "random/example.com/example.apk";
+    EXPECT_EQ(0, validate_apk_path(path3))
+            << path3 << " should be allowed as a valid path";
+
     const char *badpriv1 = TEST_APP_PRIVATE_DIR "../example.apk";
     EXPECT_EQ(-1, validate_apk_path(badpriv1))
             << badpriv1 << " should be rejected as a invalid path";
@@ -172,16 +181,16 @@
     EXPECT_EQ(-1, validate_apk_path(badpriv2))
             << badpriv2 << " should be rejected as a invalid path";
 
-    // Only one subdir should be allowed.
-    const char *bad_path3 = TEST_APP_PRIVATE_DIR "example.com/subdir/pkg.apk";
+    // Only one or two subdir should be allowed.
+    const char *bad_path3 = TEST_APP_PRIVATE_DIR "random/example.com/subdir/pkg.apk";
     EXPECT_EQ(-1, validate_apk_path(bad_path3))
             << bad_path3 << " should be rejected as a invalid path";
 
-    const char *bad_path4 = TEST_APP_PRIVATE_DIR "example.com/subdir/../pkg.apk";
+    const char *bad_path4 = TEST_APP_PRIVATE_DIR "random/example.com/subdir/../pkg.apk";
     EXPECT_EQ(-1, validate_apk_path(bad_path4))
             << bad_path4 << " should be rejected as a invalid path";
 
-    const char *bad_path5 = TEST_APP_PRIVATE_DIR "example.com1/../example.com2/pkg.apk";
+    const char *bad_path5 = TEST_APP_PRIVATE_DIR "random/example.com1/../example.com2/pkg.apk";
     EXPECT_EQ(-1, validate_apk_path(bad_path5))
             << bad_path5 << " should be rejected as a invalid path";
 }
@@ -229,10 +238,16 @@
             << badasec6 << " should be rejected as a invalid path";
 }
 
-TEST_F(UtilsTest, IsValidApkPath_TwoSubdirFail) {
-    const char *badasec7 = TEST_ASEC_DIR "com.example.asec/subdir1/pkg.apk";
-    EXPECT_EQ(-1, validate_apk_path(badasec7))
-            << badasec7 << " should be rejected as a invalid path";
+TEST_F(UtilsTest, IsValidApkPath_TwoSubdir) {
+    const char *badasec7 = TEST_ASEC_DIR "random/com.example.asec/pkg.apk";
+    EXPECT_EQ(0, validate_apk_path(badasec7))
+            << badasec7 << " should be allowed as a valid path";
+}
+
+TEST_F(UtilsTest, IsValidApkPath_ThreeSubdirFail) {
+    const char *badasec8 = TEST_ASEC_DIR "random/com.example.asec/subdir/pkg.apk";
+    EXPECT_EQ(-1, validate_apk_path(badasec8))
+            << badasec8 << " should be rejcted as an invalid path";
 }
 
 TEST_F(UtilsTest, CheckSystemApp_Dir1) {
@@ -511,8 +526,8 @@
     EXPECT_EQ(0, validate_apk_path("/data/app/com.example"));
     EXPECT_EQ(0, validate_apk_path("/data/app/com.example/file"));
     EXPECT_EQ(0, validate_apk_path("/data/app/com.example//file"));
-    EXPECT_NE(0, validate_apk_path("/data/app/com.example/dir/"));
-    EXPECT_NE(0, validate_apk_path("/data/app/com.example/dir/file"));
+    EXPECT_EQ(0, validate_apk_path("/data/app/random/com.example/"));
+    EXPECT_EQ(0, validate_apk_path("/data/app/random/com.example/file"));
     EXPECT_NE(0, validate_apk_path("/data/app/com.example/dir/dir/file"));
     EXPECT_NE(0, validate_apk_path("/data/app/com.example/dir/dir//file"));
     EXPECT_NE(0, validate_apk_path("/data/app/com.example/dir/dir/dir/file"));
@@ -527,8 +542,10 @@
     EXPECT_EQ(0, validate_apk_path_subdirs("/data/app/com.example/dir/file"));
     EXPECT_EQ(0, validate_apk_path_subdirs("/data/app/com.example/dir/dir/file"));
     EXPECT_EQ(0, validate_apk_path_subdirs("/data/app/com.example/dir/dir//file"));
-    EXPECT_NE(0, validate_apk_path_subdirs("/data/app/com.example/dir/dir/dir/file"));
-    EXPECT_NE(0, validate_apk_path_subdirs("/data/app/com.example/dir/dir/dir//file"));
+    EXPECT_EQ(0, validate_apk_path_subdirs("/data/app/com.example/dir/dir/dir/file"));
+    EXPECT_EQ(0, validate_apk_path_subdirs("/data/app/com.example/dir/dir/dir//file"));
+    EXPECT_NE(0, validate_apk_path_subdirs("/data/app/com.example/dir/dir/dir/dir/file"));
+    EXPECT_NE(0, validate_apk_path_subdirs("/data/app/com.example/dir/dir/dir/dir//file"));
 }
 
 TEST_F(UtilsTest, MatchExtension_Valid) {
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 4eb1df0..2f79552 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -945,11 +945,11 @@
 }
 
 int validate_apk_path(const char* path) {
-    return validate_apk_path_internal(path, 1 /* maxSubdirs */);
+    return validate_apk_path_internal(path, 2 /* maxSubdirs */);
 }
 
 int validate_apk_path_subdirs(const char* path) {
-    return validate_apk_path_internal(path, 3 /* maxSubdirs */);
+    return validate_apk_path_internal(path, 4 /* maxSubdirs */);
 }
 
 int ensure_config_user_dirs(userid_t userid) {
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index ae74ac3..abe6436 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -423,11 +423,12 @@
 
 void ServiceManager::handleClientCallbacks() {
     for (const auto& [name, service] : mNameToService) {
-        handleServiceClientCallback(name);
+        handleServiceClientCallback(name, true);
     }
 }
 
-ssize_t ServiceManager::handleServiceClientCallback(const std::string& serviceName) {
+ssize_t ServiceManager::handleServiceClientCallback(const std::string& serviceName,
+                                                    bool isCalledOnInterval) {
     auto serviceIt = mNameToService.find(serviceName);
     if (serviceIt == mNameToService.end() || mNameToClientCallback.count(serviceName) < 1) {
         return -1;
@@ -451,14 +452,17 @@
         service.guaranteeClient = false;
     }
 
-    if (hasClients && !service.hasClients) {
-        // client was retrieved in some other way
-        sendClientCallbackNotifications(serviceName, true);
-    }
+    // only send notifications if this was called via the interval checking workflow
+    if (isCalledOnInterval) {
+        if (hasClients && !service.hasClients) {
+            // client was retrieved in some other way
+            sendClientCallbackNotifications(serviceName, true);
+        }
 
-    // there are no more clients, but the callback has not been called yet
-    if (!hasClients && service.hasClients) {
-        sendClientCallbackNotifications(serviceName, false);
+        // there are no more clients, but the callback has not been called yet
+        if (!hasClients && service.hasClients) {
+            sendClientCallbackNotifications(serviceName, false);
+        }
     }
 
     return count;
@@ -518,7 +522,7 @@
         return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
     }
 
-    int clients = handleServiceClientCallback(name);
+    int clients = handleServiceClientCallback(name, false);
 
     // clients < 0: feature not implemented or other error. Assume clients.
     // Otherwise:
@@ -527,7 +531,7 @@
     // So, if clients > 2, then at least one other service on the system must hold a refcount.
     if (clients < 0 || clients > 2) {
         // client callbacks are either disabled or there are other clients
-        LOG(INFO) << "Tried to unregister " << name << " but there are clients: " << clients;
+        LOG(INFO) << "Tried to unregister " << name << ", but there are clients: " << clients;
         return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
     }
 
diff --git a/cmds/servicemanager/ServiceManager.h b/cmds/servicemanager/ServiceManager.h
index 77f5250..a2fc5a8 100644
--- a/cmds/servicemanager/ServiceManager.h
+++ b/cmds/servicemanager/ServiceManager.h
@@ -75,7 +75,7 @@
     void removeRegistrationCallback(const wp<IBinder>& who,
                         ServiceCallbackMap::iterator* it,
                         bool* found);
-    ssize_t handleServiceClientCallback(const std::string& serviceName);
+    ssize_t handleServiceClientCallback(const std::string& serviceName, bool isCalledOnInterval);
      // Also updates mHasClients (of what the last callback was)
     void sendClientCallbackNotifications(const std::string& serviceName, bool hasClients);
     // removes a callback from mNameToClientCallback, deleting the entry if the vector is empty
diff --git a/libs/adbd_auth/Android.bp b/libs/adbd_auth/Android.bp
index 9cf0143..8ac044c 100644
--- a/libs/adbd_auth/Android.bp
+++ b/libs/adbd_auth/Android.bp
@@ -20,11 +20,14 @@
         "-Wthread-safety",
         "-Werror",
     ],
+    stl: "libc++_static",
+
     srcs: ["adbd_auth.cpp"],
     export_include_dirs: ["include"],
 
     version_script: "libadbd_auth.map.txt",
     stubs: {
+        versions: ["1"],
         symbol_file: "libadbd_auth.map.txt",
     },
 
@@ -36,7 +39,7 @@
         }
     },
 
-    shared_libs: [
+    static_libs: [
         "libbase",
         "libcutils",
         "liblog",
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 079dd82..1ee3853 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -73,7 +73,6 @@
     // or dessert updates. Instead, apex users should use libbinder_ndk.
     apex_available: [
         "//apex_available:platform",
-        "com.android.vndk.current",
         // TODO(b/139016109) remove these three
         "com.android.media.swcodec",
         "test_com.android.media.swcodec",
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index 238c9dc..f16c39c 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -435,7 +435,8 @@
     Vector<Obituary>* obits = mObituaries;
     if(obits != nullptr) {
         if (!obits->isEmpty()) {
-            ALOGI("onLastStrongRef automatically unlinking death recipients");
+            ALOGI("onLastStrongRef automatically unlinking death recipients: %s",
+                  mDescriptorCache.size() ? String8(mDescriptorCache).c_str() : "<uncached descriptor>");
         }
 
         if (ipc) ipc->clearDeathNotification(mHandle, this);
diff --git a/libs/binder/BufferedTextOutput.cpp b/libs/binder/BufferedTextOutput.cpp
index fb424fd..856a178 100644
--- a/libs/binder/BufferedTextOutput.cpp
+++ b/libs/binder/BufferedTextOutput.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include <binder/BufferedTextOutput.h>
+#include "BufferedTextOutput.h"
 #include <binder/Debug.h>
 
 #include <cutils/atomic.h>
diff --git a/libs/binder/include/binder/BufferedTextOutput.h b/libs/binder/BufferedTextOutput.h
similarity index 100%
rename from libs/binder/include/binder/BufferedTextOutput.h
rename to libs/binder/BufferedTextOutput.h
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 5ca9156..328653a 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -85,10 +85,11 @@
     sp<AidlServiceManager> mTheRealServiceManager;
 };
 
+static Mutex gDefaultServiceManagerLock;
+static sp<IServiceManager> gDefaultServiceManager;
+
 sp<IServiceManager> defaultServiceManager()
 {
-    static Mutex gDefaultServiceManagerLock;
-    static sp<IServiceManager> gDefaultServiceManager;
 
     if (gDefaultServiceManager != nullptr) return gDefaultServiceManager;
 
@@ -106,6 +107,11 @@
     return gDefaultServiceManager;
 }
 
+void setDefaultServiceManager(const sp<IServiceManager>& sm) {
+  AutoMutex _l(gDefaultServiceManagerLock);
+  gDefaultServiceManager = sm;
+}
+
 #if !defined(__ANDROID_VNDK__) && defined(__ANDROID__)
 // IPermissionController is not accessible to vendors
 
diff --git a/libs/binder/LazyServiceRegistrar.cpp b/libs/binder/LazyServiceRegistrar.cpp
index dc9482c..f064bd7 100644
--- a/libs/binder/LazyServiceRegistrar.cpp
+++ b/libs/binder/LazyServiceRegistrar.cpp
@@ -53,14 +53,13 @@
 
     struct Service {
         sp<IBinder> service;
-        std::string name;
         bool allowIsolated;
         int dumpFlags;
     };
     /**
-     * Number of services that have been registered.
+     * Map of registered names and services
      */
-    std::vector<Service> mRegisteredServices;
+    std::map<std::string, Service> mRegisteredServices;
 };
 
 bool ClientCounterCallback::registerService(const sp<IBinder>& service, const std::string& name,
@@ -68,20 +67,24 @@
     auto manager = interface_cast<AidlServiceManager>(
                     ProcessState::self()->getContextObject(nullptr));
 
-    ALOGI("Registering service %s", name.c_str());
+    bool reRegister = mRegisteredServices.count(name) > 0;
+    std::string regStr = (reRegister) ? "Re-registering" : "Registering";
+    ALOGI("%s service %s", regStr.c_str(), name.c_str());
 
     if (!manager->addService(name.c_str(), service, allowIsolated, dumpFlags).isOk()) {
         ALOGE("Failed to register service %s", name.c_str());
         return false;
     }
 
-    if (!manager->registerClientCallback(name, service, this).isOk())
-    {
-      ALOGE("Failed to add client callback for service %s", name.c_str());
-      return false;
+    if (!manager->registerClientCallback(name, service, this).isOk()) {
+        ALOGE("Failed to add client callback for service %s", name.c_str());
+        return false;
     }
 
-    mRegisteredServices.push_back({service, name, allowIsolated, dumpFlags});
+    if (!reRegister) {
+        // Only add this when a service is added for the first time, as it is not removed
+        mRegisteredServices[name] = {service, allowIsolated, dumpFlags};
+    }
 
     return true;
 }
@@ -119,10 +122,11 @@
     for (; unRegisterIt != mRegisteredServices.end(); ++unRegisterIt) {
         auto& entry = (*unRegisterIt);
 
-        bool success = manager->tryUnregisterService(entry.name, entry.service).isOk();
+        bool success = manager->tryUnregisterService(entry.first, entry.second.service).isOk();
+
 
         if (!success) {
-            ALOGI("Failed to unregister service %s", entry.name.c_str());
+            ALOGI("Failed to unregister service %s", entry.first.c_str());
             break;
         }
     }
@@ -137,7 +141,8 @@
         auto& entry = (*reRegisterIt);
 
         // re-register entry
-        if (!registerService(entry.service, entry.name, entry.allowIsolated, entry.dumpFlags)) {
+        if (!registerService(entry.second.service, entry.first, entry.second.allowIsolated,
+                             entry.second.dumpFlags)) {
             // Must restart. Otherwise, clients will never be able to get a hold of this service.
             ALOGE("Bad state: could not re-register services");
         }
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 9be06cd..9f71f3e 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -505,7 +505,7 @@
     }
 }
 
-#if defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || (defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__))
+#if defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
 constexpr int32_t kHeader = B_PACK_CHARS('V', 'N', 'D', 'R');
 #else
 constexpr int32_t kHeader = B_PACK_CHARS('S', 'Y', 'S', 'T');
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index ce2cd99..c0f5e31 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -60,14 +60,14 @@
         : mIsMain(isMain)
     {
     }
-    
+
 protected:
     virtual bool threadLoop()
     {
         IPCThreadState::self()->joinThreadPool(mIsMain);
         return false;
     }
-    
+
     const bool mIsMain;
 };
 
@@ -296,7 +296,7 @@
 void ProcessState::expungeHandle(int32_t handle, IBinder* binder)
 {
     AutoMutex _l(mLock);
-    
+
     handle_entry* e = lookupHandleLocked(handle);
 
     // This handle may have already been replaced with a new BpBinder
@@ -387,7 +387,7 @@
 {
 
 // TODO(b/139016109): enforce in build system
-#if defined(__ANDROID_APEX__) && !defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__)
+#if defined(__ANDROID_APEX__)
     LOG_ALWAYS_FATAL("Cannot use libbinder in APEX (only system.img libbinder) since it is not stable.");
 #endif
 
@@ -416,5 +416,5 @@
     }
     mDriverFD = -1;
 }
-        
+
 } // namespace android
diff --git a/libs/binder/Static.cpp b/libs/binder/Static.cpp
index bd40536..7a77f6d 100644
--- a/libs/binder/Static.cpp
+++ b/libs/binder/Static.cpp
@@ -19,7 +19,7 @@
 
 #include "Static.h"
 
-#include <binder/BufferedTextOutput.h>
+#include "BufferedTextOutput.h"
 #include <binder/IPCThreadState.h>
 #include <utils/Log.h>
 
diff --git a/libs/binder/TEST_MAPPING b/libs/binder/TEST_MAPPING
index b3afd81..7489afa 100644
--- a/libs/binder/TEST_MAPPING
+++ b/libs/binder/TEST_MAPPING
@@ -19,7 +19,13 @@
       "name": "binderStabilityTest"
     },
     {
+      "name": "libbinder_ndk_unit_test"
+    },
+    {
       "name": "CtsNdkBinderTestCases"
+    },
+    {
+      "name": "aidl_lazy_test"
     }
   ]
 }
diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h
index 2c43263..31f022d 100644
--- a/libs/binder/include/binder/IServiceManager.h
+++ b/libs/binder/include/binder/IServiceManager.h
@@ -100,6 +100,11 @@
 
 sp<IServiceManager> defaultServiceManager();
 
+/**
+ * Directly set the default service manager. Only used for testing.
+ */
+void setDefaultServiceManager(const sp<IServiceManager>& sm);
+
 template<typename INTERFACE>
 sp<INTERFACE> waitForService(const String16& name) {
     const sp<IServiceManager> sm = defaultServiceManager();
diff --git a/libs/binder/include/binder/Stability.h b/libs/binder/include/binder/Stability.h
index b2f51d3..2894482 100644
--- a/libs/binder/include/binder/Stability.h
+++ b/libs/binder/include/binder/Stability.h
@@ -81,7 +81,7 @@
         VINTF = 0b111111,
     };
 
-#if defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || (defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__))
+#if defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
     static constexpr Level kLocalStability = Level::VENDOR;
 #else
     static constexpr Level kLocalStability = Level::SYSTEM;
diff --git a/libs/binder/ndk/include_platform/android/binder_stability.h b/libs/binder/ndk/include_platform/android/binder_stability.h
index 56d95a7..f5e8bf6 100644
--- a/libs/binder/ndk/include_platform/android/binder_stability.h
+++ b/libs/binder/ndk/include_platform/android/binder_stability.h
@@ -30,8 +30,7 @@
     FLAG_PRIVATE_VENDOR = 0x10000000,
 };
 
-#if defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || \
-        (defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__))
+#if defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
 
 enum {
     FLAG_PRIVATE_LOCAL = FLAG_PRIVATE_VENDOR,
@@ -46,8 +45,7 @@
     AIBinder_markVendorStability(binder);
 }
 
-#else  // defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || (defined(__ANDROID_VNDK__) &&
-       // !defined(__ANDROID_APEX__))
+#else  // defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
 
 enum {
     FLAG_PRIVATE_LOCAL = 0,
@@ -64,8 +62,7 @@
     AIBinder_markSystemStability(binder);
 }
 
-#endif  // defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || (defined(__ANDROID_VNDK__) &&
-        // !defined(__ANDROID_APEX__))
+#endif  // defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
 
 /**
  * This interface has system<->vendor stability
diff --git a/libs/binder/ndk/runtests.sh b/libs/binder/ndk/runtests.sh
deleted file mode 100755
index a0c49fb..0000000
--- a/libs/binder/ndk/runtests.sh
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright (C) 2018 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.
-
-if [ -z $ANDROID_BUILD_TOP ]; then
-  echo "You need to source and lunch before you can use this script"
-  exit 1
-fi
-
-set -ex
-
-function run_libbinder_ndk_test() {
-    adb shell /data/nativetest64/libbinder_ndk_test_server/libbinder_ndk_test_server &
-
-    # avoid getService 1s delay for most runs, non-critical
-    sleep 0.1
-
-    adb shell /data/nativetest64/libbinder_ndk_test_client/libbinder_ndk_test_client; \
-        adb shell killall libbinder_ndk_test_server
-}
-
-[ "$1" != "--skip-build" ] && $ANDROID_BUILD_TOP/build/soong/soong_ui.bash --make-mode \
-    MODULES-IN-frameworks-native-libs-binder-ndk
-
-adb root
-adb wait-for-device
-adb sync data
-
-# very simple unit tests, tests things outside of the NDK as well
-run_libbinder_ndk_test
-
-# CTS tests (much more comprehensive, new tests should ideally go here)
-atest android.binder.cts
diff --git a/libs/binder/ndk/test/Android.bp b/libs/binder/ndk/test/Android.bp
index daaaa5a..513d8c2 100644
--- a/libs/binder/ndk/test/Android.bp
+++ b/libs/binder/ndk/test/Android.bp
@@ -56,16 +56,17 @@
 // specifically the parts which are outside of the NDK. Actual users should
 // also instead use AIDL to generate these stubs. See android.binder.cts.
 cc_test {
-    name: "libbinder_ndk_test_client",
+    name: "libbinder_ndk_unit_test",
     defaults: ["test_libbinder_ndk_test_defaults"],
-    srcs: ["main_client.cpp"],
-}
+    srcs: ["libbinder_ndk_unit_test.cpp"],
+    static_libs: [
+        "IBinderNdkUnitTest-ndk_platform",
+    ],
+    test_suites: ["general-tests"],
+    require_root: true,
 
-cc_test {
-    name: "libbinder_ndk_test_server",
-    defaults: ["test_libbinder_ndk_test_defaults"],
-    srcs: ["main_server.cpp"],
-    gtest: false,
+    // force since binderVendorDoubleLoadTest has its own
+    auto_gen_config: true,
 }
 
 cc_test {
@@ -85,7 +86,7 @@
         "libbinder_ndk",
         "libutils",
     ],
-    test_suites: ["device-tests"],
+    test_suites: ["general-tests"],
 }
 
 aidl_interface {
@@ -95,3 +96,11 @@
         "IBinderVendorDoubleLoadTest.aidl",
     ],
 }
+
+aidl_interface {
+    name: "IBinderNdkUnitTest",
+    srcs: [
+        "IBinderNdkUnitTest.aidl",
+        "IEmpty.aidl",
+    ],
+}
diff --git a/libs/binder/ndk/test/IBinderNdkUnitTest.aidl b/libs/binder/ndk/test/IBinderNdkUnitTest.aidl
new file mode 100644
index 0000000..6e8e463
--- /dev/null
+++ b/libs/binder/ndk/test/IBinderNdkUnitTest.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+// This AIDL is to test things that can't be tested in CtsNdkBinderTestCases
+// because it requires libbinder_ndk implementation details or APIs not
+// available to apps. Please prefer adding tests to CtsNdkBinderTestCases
+// over here.
+
+import IEmpty;
+
+interface IBinderNdkUnitTest {
+    void takeInterface(IEmpty test);
+    void forceFlushCommands();
+}
diff --git a/libs/binder/ndk/test/IEmpty.aidl b/libs/binder/ndk/test/IEmpty.aidl
new file mode 100644
index 0000000..95e4341
--- /dev/null
+++ b/libs/binder/ndk/test/IEmpty.aidl
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+interface IEmpty { }
diff --git a/libs/binder/ndk/test/main_client.cpp b/libs/binder/ndk/test/libbinder_ndk_unit_test.cpp
similarity index 66%
rename from libs/binder/ndk/test/main_client.cpp
rename to libs/binder/ndk/test/libbinder_ndk_unit_test.cpp
index 8467734..51dd169 100644
--- a/libs/binder/ndk/test/main_client.cpp
+++ b/libs/binder/ndk/test/libbinder_ndk_unit_test.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include <aidl/BnBinderNdkUnitTest.h>
+#include <aidl/BnEmpty.h>
 #include <android-base/logging.h>
 #include <android/binder_ibinder_jni.h>
 #include <android/binder_manager.h>
@@ -21,6 +23,11 @@
 #include <gtest/gtest.h>
 #include <iface/iface.h>
 
+// warning: this is assuming that libbinder_ndk is using the same copy
+// of libbinder that we are.
+#include <binder/IPCThreadState.h>
+
+#include <sys/prctl.h>
 #include <chrono>
 #include <condition_variable>
 #include <mutex>
@@ -28,6 +35,65 @@
 using ::android::sp;
 
 constexpr char kExistingNonNdkService[] = "SurfaceFlinger";
+constexpr char kBinderNdkUnitTestService[] = "BinderNdkUnitTest";
+
+class MyBinderNdkUnitTest : public aidl::BnBinderNdkUnitTest {
+    ndk::ScopedAStatus takeInterface(const std::shared_ptr<aidl::IEmpty>& empty) {
+        (void)empty;
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus forceFlushCommands() {
+        // warning: this is assuming that libbinder_ndk is using the same copy
+        // of libbinder that we are.
+        android::IPCThreadState::self()->flushCommands();
+        return ndk::ScopedAStatus::ok();
+    }
+};
+
+int generatedService() {
+    ABinderProcess_setThreadPoolMaxThreadCount(0);
+
+    auto service = ndk::SharedRefBase::make<MyBinderNdkUnitTest>();
+    binder_status_t status =
+            AServiceManager_addService(service->asBinder().get(), kBinderNdkUnitTestService);
+
+    if (status != STATUS_OK) {
+        LOG(FATAL) << "Could not register: " << status << " " << kBinderNdkUnitTestService;
+    }
+
+    ABinderProcess_joinThreadPool();
+
+    return 1;  // should not return
+}
+
+// manually-written parceling class considered bad practice
+class MyFoo : public IFoo {
+    binder_status_t doubleNumber(int32_t in, int32_t* out) override {
+        *out = 2 * in;
+        LOG(INFO) << "doubleNumber (" << in << ") => " << *out;
+        return STATUS_OK;
+    }
+
+    binder_status_t die() override {
+        LOG(FATAL) << "IFoo::die called!";
+        return STATUS_UNKNOWN_ERROR;
+    }
+};
+
+int manualService(const char* instance) {
+    ABinderProcess_setThreadPoolMaxThreadCount(0);
+
+    // Strong reference to MyFoo kept by service manager.
+    binder_status_t status = (new MyFoo)->addService(instance);
+
+    if (status != STATUS_OK) {
+        LOG(FATAL) << "Could not register: " << status << " " << instance;
+    }
+
+    ABinderProcess_joinThreadPool();
+
+    return 1;  // should not return
+}
 
 // This is too slow
 // TEST(NdkBinder, GetServiceThatDoesntExist) {
@@ -87,14 +153,14 @@
     EXPECT_EQ(STATUS_DEAD_OBJECT, foo->die());
 
     foo = nullptr;
-    AIBinder_decStrong(binder);
-    binder = nullptr;
 
     std::unique_lock<std::mutex> lock(deathMutex);
     EXPECT_TRUE(deathCv.wait_for(lock, 1s, [&] { return deathRecieved; }));
     EXPECT_TRUE(deathRecieved);
 
     AIBinder_DeathRecipient_delete(recipient);
+    AIBinder_decStrong(binder);
+    binder = nullptr;
 }
 
 TEST(NdkBinder, RetrieveNonNdkService) {
@@ -196,9 +262,56 @@
     EXPECT_EQ(IFoo::getService(kInstanceName1), IFoo::getService(kInstanceName2));
 }
 
+TEST(NdkBinder, SentAidlBinderCanBeDestroyed) {
+    static volatile bool destroyed = false;
+    static std::mutex dMutex;
+    static std::condition_variable cv;
+
+    class MyEmpty : public aidl::BnEmpty {
+        virtual ~MyEmpty() {
+            destroyed = true;
+            cv.notify_one();
+        }
+    };
+
+    std::shared_ptr<MyEmpty> empty = ndk::SharedRefBase::make<MyEmpty>();
+
+    ndk::SpAIBinder binder(AServiceManager_getService(kBinderNdkUnitTestService));
+    std::shared_ptr<aidl::IBinderNdkUnitTest> service =
+            aidl::IBinderNdkUnitTest::fromBinder(binder);
+
+    EXPECT_FALSE(destroyed);
+
+    service->takeInterface(empty);
+    service->forceFlushCommands();
+    empty = nullptr;
+
+    // give other binder thread time to process commands
+    {
+        using namespace std::chrono_literals;
+        std::unique_lock<std::mutex> lk(dMutex);
+        cv.wait_for(lk, 1s, [] { return destroyed; });
+    }
+
+    EXPECT_TRUE(destroyed);
+}
+
 int main(int argc, char* argv[]) {
     ::testing::InitGoogleTest(&argc, argv);
 
+    if (fork() == 0) {
+        prctl(PR_SET_PDEATHSIG, SIGHUP);
+        return manualService(IFoo::kInstanceNameToDieFor);
+    }
+    if (fork() == 0) {
+        prctl(PR_SET_PDEATHSIG, SIGHUP);
+        return manualService(IFoo::kSomeInstanceName);
+    }
+    if (fork() == 0) {
+        prctl(PR_SET_PDEATHSIG, SIGHUP);
+        return generatedService();
+    }
+
     ABinderProcess_setThreadPoolMaxThreadCount(1);  // to recieve death notifications/callbacks
     ABinderProcess_startThreadPool();
 
diff --git a/libs/binder/ndk/test/main_server.cpp b/libs/binder/ndk/test/main_server.cpp
deleted file mode 100644
index a6e17e8..0000000
--- a/libs/binder/ndk/test/main_server.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#include <android-base/logging.h>
-#include <android/binder_process.h>
-#include <iface/iface.h>
-
-using ::android::sp;
-
-class MyFoo : public IFoo {
-    binder_status_t doubleNumber(int32_t in, int32_t* out) override {
-        *out = 2 * in;
-        LOG(INFO) << "doubleNumber (" << in << ") => " << *out;
-        return STATUS_OK;
-    }
-
-    binder_status_t die() override {
-        LOG(FATAL) << "IFoo::die called!";
-        return STATUS_UNKNOWN_ERROR;
-    }
-};
-
-int service(const char* instance) {
-    ABinderProcess_setThreadPoolMaxThreadCount(0);
-
-    // Strong reference to MyFoo kept by service manager.
-    binder_status_t status = (new MyFoo)->addService(instance);
-
-    if (status != STATUS_OK) {
-        LOG(FATAL) << "Could not register: " << status << " " << instance;
-    }
-
-    ABinderProcess_joinThreadPool();
-
-    return 1;  // should not return
-}
-
-int main() {
-    if (fork() == 0) {
-        return service(IFoo::kInstanceNameToDieFor);
-    }
-
-    return service(IFoo::kSomeInstanceName);
-}
diff --git a/libs/fakeservicemanager/Android.bp b/libs/fakeservicemanager/Android.bp
new file mode 100644
index 0000000..de32ff4
--- /dev/null
+++ b/libs/fakeservicemanager/Android.bp
@@ -0,0 +1,25 @@
+cc_defaults {
+    name: "fakeservicemanager_defaults",
+    srcs: [
+        "ServiceManager.cpp",
+    ],
+
+    shared_libs: [
+        "libbinder",
+        "libutils",
+    ],
+}
+
+cc_library {
+    name: "libfakeservicemanager",
+    defaults: ["fakeservicemanager_defaults"],
+}
+
+cc_test_host {
+    name: "fakeservicemanager_test",
+    defaults: ["fakeservicemanager_defaults"],
+    srcs: [
+        "test_sm.cpp",
+    ],
+    static_libs: ["libgmock"],
+}
diff --git a/libs/fakeservicemanager/ServiceManager.cpp b/libs/fakeservicemanager/ServiceManager.cpp
new file mode 100644
index 0000000..6964324
--- /dev/null
+++ b/libs/fakeservicemanager/ServiceManager.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#include "ServiceManager.h"
+
+namespace android {
+
+ServiceManager::ServiceManager() {}
+
+sp<IBinder> ServiceManager::getService( const String16& name) const {
+    // Servicemanager is single-threaded and cannot block. This method exists for legacy reasons.
+    return checkService(name);
+}
+
+sp<IBinder> ServiceManager::checkService( const String16& name) const {
+    auto it = mNameToService.find(name);
+    if (it == mNameToService.end()) {
+        return nullptr;
+    }
+    return it->second;
+}
+
+status_t ServiceManager::addService(const String16& name, const sp<IBinder>& service,
+                                bool /*allowIsolated*/,
+                                int /*dumpsysFlags*/) {
+    mNameToService[name] = service;
+    return NO_ERROR;
+}
+
+Vector<String16> ServiceManager::listServices(int /*dumpsysFlags*/) {
+    Vector<String16> services;
+    for (auto const& [name, service] : mNameToService) {
+        (void) service;
+         services.push_back(name);
+    }
+  return services;
+}
+
+IBinder* ServiceManager::onAsBinder() {
+    return nullptr;
+}
+
+sp<IBinder> ServiceManager::waitForService(const String16& name) {
+    return checkService(name);
+}
+
+bool ServiceManager::isDeclared(const String16& name) {
+    return mNameToService.find(name) != mNameToService.end();
+}
+
+}  // namespace android
diff --git a/libs/fakeservicemanager/ServiceManager.h b/libs/fakeservicemanager/ServiceManager.h
new file mode 100644
index 0000000..62311d4
--- /dev/null
+++ b/libs/fakeservicemanager/ServiceManager.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#pragma once
+
+#include <binder/IServiceManager.h>
+
+#include <map>
+
+namespace android {
+
+/**
+ * A local host simple implementation of IServiceManager, that does not
+ * communicate over binder.
+*/
+class ServiceManager : public IServiceManager {
+public:
+    ServiceManager();
+
+    /**
+     * Equivalent of checkService.
+     */
+    sp<IBinder> getService( const String16& name) const override;
+
+    /**
+     * Retrieve an existing service, non-blocking.
+     */
+    sp<IBinder> checkService( const String16& name) const override;
+
+    /**
+     * Register a service.
+     */
+    status_t addService(const String16& name, const sp<IBinder>& service,
+                        bool allowIsolated = false,
+                        int dumpsysFlags = DUMP_FLAG_PRIORITY_DEFAULT) override;
+
+    /**
+     * Return list of all existing services.
+     */
+    Vector<String16> listServices(int dumpsysFlags = 0) override;
+
+    IBinder* onAsBinder() override;
+
+    /**
+     * Effectively no-oped in this implementation - equivalent to checkService.
+     */
+    sp<IBinder> waitForService(const String16& name) override;
+
+    /**
+     * Check if a service is declared (e.g. VINTF manifest).
+     *
+     * If this returns true, waitForService should always be able to return the
+     * service.
+     */
+     bool isDeclared(const String16& name) override;
+
+private:
+    std::map<String16, sp<IBinder>> mNameToService;
+};
+
+}  // namespace android
diff --git a/libs/fakeservicemanager/test_sm.cpp b/libs/fakeservicemanager/test_sm.cpp
new file mode 100644
index 0000000..71e5abe
--- /dev/null
+++ b/libs/fakeservicemanager/test_sm.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+#include <binder/Binder.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
+
+#include "ServiceManager.h"
+
+using android::sp;
+using android::BBinder;
+using android::IBinder;
+using android::OK;
+using android::status_t;
+using android::ServiceManager;
+using android::String16;
+using android::IServiceManager;
+using testing::ElementsAre;
+
+static sp<IBinder> getBinder() {
+    class LinkableBinder : public BBinder {
+        status_t linkToDeath(const sp<DeathRecipient>&, void*, uint32_t) override {
+            // let SM linkToDeath
+            return OK;
+        }
+    };
+
+    return new LinkableBinder;
+}
+
+TEST(AddService, HappyHappy) {
+    auto sm = new ServiceManager();
+    EXPECT_EQ(sm->addService(String16("foo"), getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT), OK);
+}
+
+TEST(AddService, HappyOverExistingService) {
+    auto sm = new ServiceManager();
+    EXPECT_EQ(sm->addService(String16("foo"), getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT), OK);
+    EXPECT_EQ(sm->addService(String16("foo"), getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT), OK);
+}
+
+TEST(GetService, HappyHappy) {
+    auto sm = new ServiceManager();
+    sp<IBinder> service = getBinder();
+
+    EXPECT_EQ(sm->addService(String16("foo"), service, false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT), OK);
+
+    EXPECT_EQ(sm->getService(String16("foo")), service);
+}
+
+TEST(GetService, NonExistant) {
+    auto sm = new ServiceManager();
+
+    EXPECT_EQ(sm->getService(String16("foo")), nullptr);
+}
+
+TEST(ListServices, AllServices) {
+    auto sm = new ServiceManager();
+
+    EXPECT_EQ(sm->addService(String16("sd"), getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT), OK);
+    EXPECT_EQ(sm->addService(String16("sc"), getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_NORMAL), OK);
+    EXPECT_EQ(sm->addService(String16("sb"), getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_HIGH), OK);
+    EXPECT_EQ(sm->addService(String16("sa"), getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL), OK);
+
+    android::Vector<String16> out = sm->listServices(IServiceManager::DUMP_FLAG_PRIORITY_ALL);
+
+    // all there and in the right order
+    EXPECT_THAT(out, ElementsAre(String16("sa"), String16("sb"), String16("sc"),
+        String16("sd")));
+}
+
+TEST(WaitForService, NonExistant) {
+    auto sm = new ServiceManager();
+
+    EXPECT_EQ(sm->waitForService(String16("foo")), nullptr);
+}
+
+TEST(WaitForService, HappyHappy) {
+    auto sm = new ServiceManager();
+    sp<IBinder> service = getBinder();
+
+    EXPECT_EQ(sm->addService(String16("foo"), service, false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT), OK);
+
+    EXPECT_EQ(sm->waitForService(String16("foo")), service);
+}
+
+TEST(IsDeclared, NonExistant) {
+    auto sm = new ServiceManager();
+
+    EXPECT_FALSE(sm->isDeclared(String16("foo")));
+}
+
+TEST(IsDeclared, HappyHappy) {
+    auto sm = new ServiceManager();
+    sp<IBinder> service = getBinder();
+
+    EXPECT_EQ(sm->addService(String16("foo"), service, false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT), OK);
+
+    EXPECT_TRUE(sm->isDeclared(String16("foo")));
+}