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/core/java/com/android/internal/os/InstallerConnection.java b/core/java/com/android/internal/os/InstallerConnection.java
index 13d046e..830da79 100644
--- a/core/java/com/android/internal/os/InstallerConnection.java
+++ b/core/java/com/android/internal/os/InstallerConnection.java
@@ -21,6 +21,8 @@
 import android.os.SystemClock;
 import android.util.Slog;
 
+import com.android.internal.util.Preconditions;
+
 import libcore.io.IoUtils;
 import libcore.io.Streams;
 
@@ -42,11 +44,22 @@
     private OutputStream mOut;
     private LocalSocket mSocket;
 
+    private volatile Object mWarnIfHeld;
+
     private final byte buf[] = new byte[1024];
 
     public InstallerConnection() {
     }
 
+    /**
+     * Yell loudly if someone tries making future calls while holding a lock on
+     * the given object.
+     */
+    public void setWarnIfHeld(Object warnIfHeld) {
+        Preconditions.checkState(mWarnIfHeld == null);
+        mWarnIfHeld = Preconditions.checkNotNull(warnIfHeld);
+    }
+
     public synchronized String transact(String cmd) {
         if (!connect()) {
             Slog.e(TAG, "connection failed");
@@ -84,6 +97,11 @@
     }
 
     public int execute(String cmd) {
+        if (mWarnIfHeld != null && Thread.holdsLock(mWarnIfHeld)) {
+            Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding 0x"
+                    + Integer.toHexString(System.identityHashCode(mWarnIfHeld)), new Throwable());
+        }
+
         String res = transact(cmd);
         try {
             return Integer.parseInt(res);