Fix crash in PendingIntentRecord debug output.

Add null checks to a few places to avoid crashes when dumping
debug data.

Also add some sanity checks for accessing content providers in
the activity manager.
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 7f9a5c6..1070f08 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -24,6 +24,7 @@
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.HashMap;
 
 /**
  * Provides access to an application's raw asset files; see {@link Resources}
@@ -59,6 +60,8 @@
     private static final String TAG = "AssetManager";
     private static final boolean localLOGV = Config.LOGV || false;
     
+    private static final boolean DEBUG_REFS = false;
+    
     private static final Object sSync = new Object();
     private static AssetManager sSystem = null;
 
@@ -72,6 +75,7 @@
     
     private int mNumRefs = 1;
     private boolean mOpen = true;
+    private HashMap<Integer, RuntimeException> mRefStacks; 
  
     /**
      * Create a new AssetManager containing only the basic system assets.
@@ -82,6 +86,10 @@
      */
     public AssetManager() {
         synchronized (this) {
+            if (DEBUG_REFS) {
+                mNumRefs = 0;
+                incRefsLocked(this.hashCode());
+            }
             init();
             if (localLOGV) Log.v(TAG, "New asset manager: " + this);
             ensureSystemAssets();
@@ -99,6 +107,12 @@
     }
     
     private AssetManager(boolean isSystem) {
+        if (DEBUG_REFS) {
+            synchronized (this) {
+                mNumRefs = 0;
+                incRefsLocked(this.hashCode());
+            }
+        }
         init();
         if (localLOGV) Log.v(TAG, "New asset manager: " + this);
     }
@@ -122,7 +136,7 @@
             //                   + ", released=" + mReleased);
             if (mOpen) {
                 mOpen = false;
-                decRefsLocked();
+                decRefsLocked(this.hashCode());
             }
         }
     }
@@ -298,8 +312,9 @@
             }
             int asset = openAsset(fileName, accessMode);
             if (asset != 0) {
-                mNumRefs++;
-                return new AssetInputStream(asset);
+                AssetInputStream res = new AssetInputStream(asset);
+                incRefsLocked(res.hashCode());
+                return res;
             }
         }
         throw new FileNotFoundException("Asset file: " + fileName);
@@ -389,8 +404,9 @@
             }
             int asset = openNonAssetNative(cookie, fileName, accessMode);
             if (asset != 0) {
-                mNumRefs++;
-                return new AssetInputStream(asset);
+                AssetInputStream res = new AssetInputStream(asset);
+                incRefsLocked(res.hashCode());
+                return res;
             }
         }
         throw new FileNotFoundException("Asset absolute file: " + fileName);
@@ -468,16 +484,17 @@
             }
             int xmlBlock = openXmlAssetNative(cookie, fileName);
             if (xmlBlock != 0) {
-                mNumRefs++;
-                return new XmlBlock(this, xmlBlock);
+                XmlBlock res = new XmlBlock(this, xmlBlock);
+                incRefsLocked(res.hashCode());
+                return res;
             }
         }
         throw new FileNotFoundException("Asset XML file: " + fileName);
     }
 
-    /*package*/ void xmlBlockGone() {
+    /*package*/ void xmlBlockGone(int id) {
         synchronized (this) {
-            decRefsLocked();
+            decRefsLocked(id);
         }
     }
 
@@ -486,20 +503,34 @@
             if (!mOpen) {
                 throw new RuntimeException("Assetmanager has been closed");
             }
-            mNumRefs++;
-            return newTheme();
+            int res = newTheme();
+            incRefsLocked(res);
+            return res;
         }
     }
 
     /*package*/ final void releaseTheme(int theme) {
         synchronized (this) {
             deleteTheme(theme);
-            decRefsLocked();
+            decRefsLocked(theme);
         }
     }
 
     protected void finalize() throws Throwable {
-        destroy();
+        try {
+            if (DEBUG_REFS && mNumRefs != 0) {
+                Log.w(TAG, "AssetManager " + this
+                        + " finalized with non-zero refs: " + mNumRefs);
+                if (mRefStacks != null) {
+                    for (RuntimeException e : mRefStacks.values()) {
+                        Log.w(TAG, "Reference from here", e);
+                    }
+                }
+            }
+            destroy();
+        } finally {
+            super.finalize();
+        }
     }
     
     public final class AssetInputStream extends InputStream {
@@ -526,7 +557,7 @@
                 if (mAsset != 0) {
                     destroyAsset(mAsset);
                     mAsset = 0;
-                    decRefsLocked();
+                    decRefsLocked(hashCode());
                 }
             }
         }
@@ -710,7 +741,22 @@
     private native final void init();
     private native final void destroy();
 
-    private final void decRefsLocked() {
+    private final void incRefsLocked(int id) {
+        if (DEBUG_REFS) {
+            if (mRefStacks == null) {
+                mRefStacks = new HashMap<Integer, RuntimeException>();
+                RuntimeException ex = new RuntimeException();
+                ex.fillInStackTrace();
+                mRefStacks.put(this.hashCode(), ex);
+            }
+        }
+        mNumRefs++;
+    }
+    
+    private final void decRefsLocked(int id) {
+        if (DEBUG_REFS && mRefStacks != null) {
+            mRefStacks.remove(id);
+        }
         mNumRefs--;
         //System.out.println("Dec streams: mNumRefs=" + mNumRefs
         //                   + " mReleased=" + mReleased);
diff --git a/core/java/android/content/res/XmlBlock.java b/core/java/android/content/res/XmlBlock.java
index f800232..3c2c30a 100644
--- a/core/java/android/content/res/XmlBlock.java
+++ b/core/java/android/content/res/XmlBlock.java
@@ -59,7 +59,7 @@
         if (mOpenCount == 0) {
             nativeDestroy(mNative);
             if (mAssets != null) {
-                mAssets.xmlBlockGone();
+                mAssets.xmlBlockGone(hashCode());
             }
         }
     }
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 4169cc5..7b64704 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -7615,6 +7615,15 @@
                                     ? cpi.readPermission : cpi.writePermission);
                 }
 
+                if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
+                        && !cpi.processName.equals("system")) {
+                    // If this content provider does not run in the system
+                    // process, and the system is not yet ready to run other
+                    // processes, then fail fast instead of hanging.
+                    throw new IllegalArgumentException(
+                            "Attempt to launch content provider before system ready");
+                }
+                
                 cpr = (ContentProviderRecord)mProvidersByClass.get(cpi.name);
                 final boolean firstClass = cpr == null;
                 if (firstClass) {
@@ -7862,6 +7871,16 @@
     public static final void installSystemProviders() {
         ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
         List providers = mSelf.generateApplicationProvidersLocked(app);
+        if (providers != null) {
+            for (int i=providers.size()-1; i>=0; i--) {
+                ProviderInfo pi = (ProviderInfo)providers.get(i);
+                if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
+                    Log.w(TAG, "Not installing system proc provider " + pi.name
+                            + ": not system .apk");
+                    providers.remove(i);
+                }
+            }
+        }
         mSystemThread.installSystemProviders(providers);
     }
 
diff --git a/services/java/com/android/server/am/PendingIntentRecord.java b/services/java/com/android/server/am/PendingIntentRecord.java
index 94b5f56..fac47d7 100644
--- a/services/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/java/com/android/server/am/PendingIntentRecord.java
@@ -145,8 +145,9 @@
         
         public String toString() {
             return "Key{" + typeName() + " pkg=" + packageName
-                + " intent=" + requestIntent.toShortString(true, false) + " flags=0x"
-                + Integer.toHexString(flags) + "}";
+                + " intent="
+                + (requestIntent != null ? requestIntent.toShortString(true, false) : "<null>")
+                + " flags=0x" + Integer.toHexString(flags) + "}";
         }
         
         String typeName() {
@@ -295,8 +296,10 @@
             pw.print(prefix); pw.print("requestCode="); pw.print(key.requestCode);
                     pw.print(" requestResolvedType="); pw.println(key.requestResolvedType);
         }
-        pw.print(prefix); pw.print("requestIntent=");
-                pw.println(key.requestIntent.toShortString(true, true));
+        if (key.requestIntent != null) {
+            pw.print(prefix); pw.print("requestIntent=");
+                    pw.println(key.requestIntent.toShortString(true, true));
+        }
         if (sent || canceled) {
             pw.print(prefix); pw.print("sent="); pw.print(sent);
                     pw.print(" canceled="); pw.println(canceled);