Yell when calling installd with PM lock held.

As a matter of policy, we should never be holding the mPackages lock
while calling down into installd.  This little bit of logic helps us
catch accidental cases where this happens.

Change-Id: I676c81df43ef936ffd36290d45a79429630c1b4b
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 87ae3dc..a7879c6 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -1440,7 +1440,7 @@
         mConnector = new NativeDaemonConnector(this, "vold", MAX_CONTAINERS * 2, VOLD_TAG, 25,
                 null);
         mConnector.setDebug(true);
-        mConnector.setLockWarning(mLock);
+        mConnector.setWarnIfHeld(mLock);
 
         Thread thread = new Thread(mConnector, VOLD_TAG);
         thread.start();
diff --git a/services/core/java/com/android/server/NativeDaemonConnector.java b/services/core/java/com/android/server/NativeDaemonConnector.java
index 3a6fa05..e6b6074 100644
--- a/services/core/java/com/android/server/NativeDaemonConnector.java
+++ b/services/core/java/com/android/server/NativeDaemonConnector.java
@@ -25,10 +25,10 @@
 import android.os.PowerManager;
 import android.os.SystemClock;
 import android.util.LocalLog;
-import android.util.Log;
 import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
 import com.google.android.collect.Lists;
 
 import java.io.FileDescriptor;
@@ -58,7 +58,7 @@
     private LocalLog mLocalLog;
 
     private volatile boolean mDebug = false;
-    private volatile Object mLockWarning;
+    private volatile Object mWarnIfHeld;
 
     private final ResponseQueue mResponseQueue;
 
@@ -110,11 +110,12 @@
     }
 
     /**
-     * Yell loudly if someone tries making future {@link #execute(Command)} calls while holding a
-     * lock on the given object.
+     * Yell loudly if someone tries making future {@link #execute(Command)}
+     * calls while holding a lock on the given object.
      */
-    public void setLockWarning(Object lockWarning) {
-        mLockWarning = lockWarning;
+    public void setWarnIfHeld(Object warnIfHeld) {
+        Preconditions.checkState(mWarnIfHeld == null);
+        mWarnIfHeld = Preconditions.checkNotNull(warnIfHeld);
     }
 
     @Override
@@ -404,8 +405,9 @@
      */
     public NativeDaemonEvent[] executeForList(long timeoutMs, String cmd, Object... args)
             throws NativeDaemonConnectorException {
-        if (mLockWarning != null && Thread.holdsLock(mLockWarning)) {
-            Log.wtf(TAG, "Calling thread is holding lock " + mLockWarning, new Throwable());
+        if (mWarnIfHeld != null && Thread.holdsLock(mWarnIfHeld)) {
+            Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding 0x"
+                    + Integer.toHexString(System.identityHashCode(mWarnIfHeld)), new Throwable());
         }
 
         final long startTime = SystemClock.elapsedRealtime();
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index d867616..150c849 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -53,6 +53,14 @@
         mInstaller = new InstallerConnection();
     }
 
+    /**
+     * Yell loudly if someone tries making future calls while holding a lock on
+     * the given object.
+     */
+    public void setWarnIfHeld(Object warnIfHeld) {
+        mInstaller.setWarnIfHeld(warnIfHeld);
+    }
+
     @Override
     public void onStart() {
         Slog.i(TAG, "Waiting for installd to be ready.");
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c497ad4..08f9bd5 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2391,6 +2391,11 @@
         // tidy.
         Runtime.getRuntime().gc();
 
+        // The initial scanning above does many calls into installd while
+        // holding the mPackages lock, but we're mostly interested in yelling
+        // once we have a booted system.
+        mInstaller.setWarnIfHeld(mPackages);
+
         // Expose private service for system components to use.
         LocalServices.addService(PackageManagerInternal.class, new PackageManagerInternalImpl());
     }