Fix some random bugs.

2185256: After open &close of device keyboard shortcut does not added to Home desktop.

ActivityThread was losing the last saved state when restarting or launching into
a paused state.

2366174: defaults not cleared when they should be

PackageManagerService now removes any preferred activity records for a package
when it is uninstalled.

2154556: Battery stats can have an unbounded number of wake locks

We now start combining wake locks into one shared record when we hit a
maximum limit (currently 20).

2442519: Foreground services can have no notification by providing a bogus one.

If the notification manager rejects our notification, the service is forced to
no longer be in the foreground.

2442383: Finalization issues in com.android.server.am.PendingIntentRecord.java

Cleaned up finalization to call super class and avoid the big activity manager
lock (we still need to use the locks inside of the message system, but these
are much less likely to be a problem).

2284190: Cannot call a phone number using adb

We weren't getting the calling uid/pid in startActivity() if the caller did not
supply an application record.
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 13cc3ba..0355016 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -2495,7 +2495,6 @@
                             " did not call through to super.onPostCreate()");
                     }
                 }
-                r.state = null;
             }
             r.paused = true;
 
@@ -2526,6 +2525,7 @@
 
         if (a != null) {
             r.createdConfig = new Configuration(mConfiguration);
+            Bundle oldState = r.state;
             handleResumeActivity(r.token, false, r.isForward);
 
             if (!r.activity.mFinished && r.startsNotResumed) {
@@ -2541,6 +2541,9 @@
                 try {
                     r.activity.mCalled = false;
                     mInstrumentation.callActivityOnPause(r.activity);
+                    // We need to keep around the original state, in case
+                    // we need to be created again.
+                    r.state = oldState;
                     if (!r.activity.mCalled) {
                         throw new SuperNotCalledException(
                             "Activity " + r.intent.getComponent().toShortString() +
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index dfcc8f7..71ccb3b 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -59,6 +59,13 @@
     // Current on-disk Parcel version
     private static final int VERSION = 42;
 
+    // The maximum number of names wakelocks we will keep track of
+    // per uid; once the limit is reached, we batch the remaining wakelocks
+    // in to one common name.
+    private static final int MAX_WAKELOCKS_PER_UID = 20;
+    
+    private static final String BATCHED_WAKELOCK_NAME = "*overflow*";
+    
     private static int sNumSpeedSteps;
 
     private final File mFile;
@@ -1757,7 +1764,12 @@
                 String wakelockName = in.readString();
                 Uid.Wakelock wakelock = new Wakelock();
                 wakelock.readFromParcelLocked(unpluggables, in);
-                mWakelockStats.put(wakelockName, wakelock);
+                if (mWakelockStats.size() < MAX_WAKELOCKS_PER_UID) {
+                    // We will just drop some random set of wakelocks if
+                    // the previous run of the system was an older version
+                    // that didn't impose a limit.
+                    mWakelockStats.put(wakelockName, wakelock);
+                }
             }
 
             int numSensors = in.readInt();
@@ -2583,8 +2595,14 @@
         public StopwatchTimer getWakeTimerLocked(String name, int type) {
             Wakelock wl = mWakelockStats.get(name);
             if (wl == null) {
-                wl = new Wakelock();
-                mWakelockStats.put(name, wl);
+                if (mWakelockStats.size() > MAX_WAKELOCKS_PER_UID) {
+                    name = BATCHED_WAKELOCK_NAME;
+                    wl = mWakelockStats.get(name);
+                }
+                if (wl == null) {
+                    wl = new Wakelock();
+                    mWakelockStats.put(name, wl);
+                }
             }
             StopwatchTimer t = null;
             switch (type) {
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 4fdcd59..4a7fc9c 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -5704,6 +5704,18 @@
                 // remove permissions associated with package
                 mSettings.updateSharedUserPermsLP(deletedPs, mGlobalGids);
             }
+            if (deletedPs != null) {
+                // remove from preferred activities.
+                ArrayList<PreferredActivity> removed = new ArrayList<PreferredActivity>();
+                for (PreferredActivity pa : mSettings.mPreferredActivities.filterSet()) {
+                    if (pa.mActivity.getPackageName().equals(deletedPs.name)) {
+                        removed.add(pa);
+                    }
+                }
+                for (PreferredActivity pa : removed) {
+                    mSettings.mPreferredActivities.removeFilter(pa);
+                }
+            }
             // Save settings now
             mSettings.writeLP();
         }
@@ -7461,9 +7473,9 @@
                         Log.w(TAG, "Trying to update system app code path from " +
                                 p.codePathString + " to " + codePath.toString());
                     } else {
-                        // Let the app continue with previous uid if code path changes.
-                        reportSettingsProblem(Log.WARN,
-                                "Package " + name + " codePath changed from " + p.codePath
+                        // Just a change in the code path is not an issue, but
+                        // let's log a message about it.
+                        Log.i(TAG, "Package " + name + " codePath changed from " + p.codePath
                                 + " to " + codePath + "; Retaining data and using new");
                     }
                 }
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 5b37f47..4169cc5 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -135,6 +135,7 @@
     static final boolean DEBUG_VISBILITY = localLOGV || false;
     static final boolean DEBUG_PROCESSES = localLOGV || false;
     static final boolean DEBUG_PROVIDER = localLOGV || false;
+    static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
     static final boolean DEBUG_USER_LEAVING = localLOGV || false;
     static final boolean DEBUG_RESULTS = localLOGV || false;
     static final boolean DEBUG_BACKUP = localLOGV || false;
@@ -968,6 +969,7 @@
     static final int PROC_START_TIMEOUT_MSG = 20;
     static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
     static final int KILL_APPLICATION_MSG = 22;
+    static final int FINALIZE_PENDING_INTENT_MSG = 23;
 
     AlertDialog mUidAlert;
 
@@ -1189,6 +1191,9 @@
                     forceStopPackageLocked(pkg, uid, restart, false, true);
                 }
             } break;
+            case FINALIZE_PENDING_INTENT_MSG: {
+                ((PendingIntentRecord)msg.obj).completeFinalize();
+            } break;
             }
         }
     };
@@ -3599,10 +3604,18 @@
         }
 
         synchronized(this) {
+            int callingPid;
+            int callingUid;
+            if (caller == null) {
+                callingPid = Binder.getCallingPid();
+                callingUid = Binder.getCallingUid();
+            } else {
+                callingPid = callingUid = -1;
+            }
             final long origId = Binder.clearCallingIdentity();
             int res = startActivityLocked(caller, intent, resolvedType,
                     grantedUriPermissions, grantedMode, aInfo,
-                    resultTo, resultWho, requestCode, -1, -1,
+                    resultTo, resultWho, requestCode, callingPid, callingUid,
                     onlyIfNeeded, componentSpecified);
             Binder.restoreCallingIdentity(origId);
             return res;
@@ -6166,10 +6179,15 @@
             return;
         }
 
+        if (DEBUG_URI_PERMISSION) Log.v(TAG, 
+                "Requested grant " + targetPkg + " permission to " + uri);
+        
         final IPackageManager pm = ActivityThread.getPackageManager();
 
         // If this is not a content: uri, we can't do anything with it.
         if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
+            if (DEBUG_URI_PERMISSION) Log.v(TAG, 
+                    "Can't grant URI permission for non-content URI: " + uri);
             return;
         }
 
@@ -6195,6 +6213,8 @@
         try {
             targetUid = pm.getPackageUid(targetPkg);
             if (targetUid < 0) {
+                if (DEBUG_URI_PERMISSION) Log.v(TAG, 
+                        "Can't grant URI permission no uid for: " + targetPkg);
                 return;
             }
         } catch (RemoteException ex) {
@@ -6204,17 +6224,12 @@
         // First...  does the target actually need this permission?
         if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
             // No need to grant the target this permission.
+            if (DEBUG_URI_PERMISSION) Log.v(TAG, 
+                    "Target " + targetPkg + " already has full permission to " + uri);
             return;
         }
 
-        // Second...  maybe someone else has already granted the
-        // permission?
-        if (checkUriPermissionLocked(uri, targetUid, modeFlags)) {
-            // No need to grant the target this permission.
-            return;
-        }
-
-        // Third...  is the provider allowing granting of URI permissions?
+        // Second...  is the provider allowing granting of URI permissions?
         if (!pi.grantUriPermissions) {
             throw new SecurityException("Provider " + pi.packageName
                     + "/" + pi.name
@@ -6239,7 +6254,7 @@
             }
         }
 
-        // Fourth...  does the caller itself have permission to access
+        // Third...  does the caller itself have permission to access
         // this uri?
         if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
             if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
@@ -6252,6 +6267,9 @@
         // to the uri, and the target doesn't.  Let's now give this to
         // the target.
 
+        if (DEBUG_URI_PERMISSION) Log.v(TAG, 
+                "Granting " + targetPkg + " permission to " + uri);
+        
         HashMap<Uri, UriPermission> targetUris
                 = mGrantedUriPermissions.get(targetUid);
         if (targetUris == null) {
@@ -6325,6 +6343,8 @@
             HashMap<Uri, UriPermission> perms
                     = mGrantedUriPermissions.get(perm.uid);
             if (perms != null) {
+                if (DEBUG_URI_PERMISSION) Log.v(TAG, 
+                        "Removing " + perm.uid + " permission to " + perm.uri);
                 perms.remove(perm.uri);
                 if (perms.size() == 0) {
                     mGrantedUriPermissions.remove(perm.uid);
@@ -6364,6 +6384,9 @@
             return;
         }
 
+        if (DEBUG_URI_PERMISSION) Log.v(TAG, 
+                "Revoking all granted permissions to " + uri);
+        
         final IPackageManager pm = ActivityThread.getPackageManager();
 
         final String authority = uri.getAuthority();
@@ -6422,6 +6445,8 @@
                             continue toploop;
                         }
                     }
+                    if (DEBUG_URI_PERMISSION) Log.v(TAG, 
+                            "Revoking " + perm.uid + " permission to " + perm.uri);
                     perm.clearModes(modeFlags);
                     if (perm.modeFlags == 0) {
                         it.remove();
diff --git a/services/java/com/android/server/am/PendingIntentRecord.java b/services/java/com/android/server/am/PendingIntentRecord.java
index b3086d5..94b5f56 100644
--- a/services/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/java/com/android/server/am/PendingIntentRecord.java
@@ -262,17 +262,26 @@
     }
     
     protected void finalize() throws Throwable {
-        if (!canceled) {
-            synchronized(owner) {
-                WeakReference<PendingIntentRecord> current =
-                        owner.mIntentSenderRecords.get(key);
-                if (current == ref) {
-                    owner.mIntentSenderRecords.remove(key);
-                }
+        try {
+            if (!canceled) {
+                owner.mHandler.sendMessage(owner.mHandler.obtainMessage(
+                        ActivityManagerService.FINALIZE_PENDING_INTENT_MSG, this));
             }
+        } finally {
+            super.finalize();
         }
     }
 
+    public void completeFinalize() {
+        synchronized(owner) {
+            WeakReference<PendingIntentRecord> current =
+                    owner.mIntentSenderRecords.get(key);
+            if (current == ref) {
+                owner.mIntentSenderRecords.remove(key);
+            }
+        }
+    }
+    
     void dump(PrintWriter pw, String prefix) {
         pw.print(prefix); pw.print("uid="); pw.print(uid);
                 pw.print(" packageName="); pw.print(key.packageName);
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index 2f2cc32..5a02c40 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -269,8 +269,12 @@
                         inm.enqueueNotification(localPackageName, localForegroundId,
                                 localForegroundNoti, outId);
                     } catch (RuntimeException e) {
-                        Log.w(ActivityManagerService.TAG, "Error showing notification for service",
-                            e);
+                        Log.w(ActivityManagerService.TAG,
+                                "Error showing notification for service", e);
+                        // If it gave us a garbage notification, it doesn't
+                        // get to be foreground.
+                        ams.setServiceForeground(name, ServiceRecord.this,
+                                localForegroundId, null, true);
                     } catch (RemoteException e) {
                     }
                 }
@@ -293,8 +297,8 @@
                     try {
                         inm.cancelNotification(localPackageName, localForegroundId);
                     } catch (RuntimeException e) {
-                        Log.w(ActivityManagerService.TAG, "Error canceling notification for"
-                            + " service", e);
+                        Log.w(ActivityManagerService.TAG,
+                                "Error canceling notification for service", e);
                     } catch (RemoteException e) {
                     }
                 }