OSDN Git Service

defaultServiceManager wait for service manager ready
authorTodd Poynor <toddpoynor@google.com>
Wed, 19 Jun 2013 00:25:37 +0000 (17:25 -0700)
committerTodd Poynor <toddpoynor@google.com>
Wed, 24 Jul 2013 23:18:12 +0000 (16:18 -0700)
If the service manager is not ready when we attempt to create a local
proxy, fail and retry.

Change-Id: I7d7300bc07cd70608793479aa3da282d066da7f6

libs/binder/IServiceManager.cpp
libs/binder/ProcessState.cpp

index 1750640..a341ca8 100644 (file)
@@ -37,9 +37,11 @@ sp<IServiceManager> defaultServiceManager()
     
     {
         AutoMutex _l(gDefaultServiceManagerLock);
-        if (gDefaultServiceManager == NULL) {
+        while (gDefaultServiceManager == NULL) {
             gDefaultServiceManager = interface_cast<IServiceManager>(
                 ProcessState::self()->getContextObject(NULL));
+            if (gDefaultServiceManager == NULL)
+                sleep(1);
         }
     }
     
index 294e1d4..c1e49bc 100644 (file)
@@ -194,6 +194,33 @@ sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
         // in getWeakProxyForHandle() for more info about this.
         IBinder* b = e->binder;
         if (b == NULL || !e->refs->attemptIncWeak(this)) {
+            if (handle == 0) {
+                // Special case for context manager...
+                // The context manager is the only object for which we create
+                // a BpBinder proxy without already holding a reference.
+                // Perform a dummy transaction to ensure the context manager
+                // is registered before we create the first local reference
+                // to it (which will occur when creating the BpBinder).
+                // If a local reference is created for the BpBinder when the
+                // context manager is not present, the driver will fail to
+                // provide a reference to the context manager, but the
+                // driver API does not return status.
+                //
+                // Note that this is not race-free if the context manager
+                // dies while this code runs.
+                //
+                // TODO: add a driver API to wait for context manager, or
+                // stop special casing handle 0 for context manager and add
+                // a driver API to get a handle to the context manager with
+                // proper reference counting.
+
+                Parcel data;
+                status_t status = IPCThreadState::self()->transact(
+                        0, IBinder::PING_TRANSACTION, data, NULL, 0);
+                if (status == DEAD_OBJECT)
+                   return NULL;
+            }
+
             b = new BpBinder(handle); 
             e->binder = b;
             if (b) e->refs = b->getWeakRefs();