Maybe fix issue #7596986: Frequent runtime restarts; IAE at...

...android.os.Parcel.nativeAppendFrom(Native Method)

The failing stack trace is:

11-20 20:29:04.365 19154 19170 E AndroidRuntime: java.lang.IllegalArgumentException
11-20 20:29:04.365 19154 19170 E AndroidRuntime:        at android.os.Parcel.nativeAppendFrom(Native Method)
11-20 20:29:04.365 19154 19170 E AndroidRuntime:        at android.os.Parcel.appendFrom(Parcel.java:428)
11-20 20:29:04.365 19154 19170 E AndroidRuntime:        at android.os.Bundle.writeToParcel(Bundle.java:1613)
11-20 20:29:04.365 19154 19170 E AndroidRuntime:        at android.os.Parcel.writeBundle(Parcel.java:605)
11-20 20:29:04.365 19154 19170 E AndroidRuntime:        at android.location.Location.writeToParcel(Location.java:903)
11-20 20:29:04.365 19154 19170 E AndroidRuntime:        at android.os.Parcel.writeParcelable(Parcel.java:1254)
11-20 20:29:04.365 19154 19170 E AndroidRuntime:        at android.os.Parcel.writeValue(Parcel.java:1173)
11-20 20:29:04.365 19154 19170 E AndroidRuntime:        at android.os.Parcel.writeMapInternal(Parcel.java:591)
11-20 20:29:04.365 19154 19170 E AndroidRuntime:        at android.os.Bundle.writeToParcel(Bundle.java:1619)
11-20 20:29:04.365 19154 19170 E AndroidRuntime:        at android.os.Parcel.writeBundle(Parcel.java:605)
11-20 20:29:04.365 19154 19170 E AndroidRuntime:        at android.location.Location.writeToParcel(Location.java:903)
11-20 20:29:04.365 19154 19170 E AndroidRuntime:        at android.os.Parcel.writeParcelable(Parcel.java:1254)
11-20 20:29:04.365 19154 19170 E AndroidRuntime:        at android.os.Parcel.writeValue(Parcel.java:1173)
11-20 20:29:04.365 19154 19170 E AndroidRuntime:        at android.os.Parcel.writeMapInternal(Parcel.java:591)
11-20 20:29:04.365 19154 19170 E AndroidRuntime:        at android.os.Bundle.writeToParcel(Bundle.java:1619)
11-20 20:29:04.365 19154 19170 E AndroidRuntime:        at android.os.Parcel.writeBundle(Parcel.java:605)
11-20 20:29:04.365 19154 19170 E AndroidRuntime:        at android.content.Intent.writeToParcel(Intent.java:6660)
11-20 20:29:04.365 19154 19170 E AndroidRuntime:        at android.app.ApplicationThreadProxy.scheduleReceiver(ApplicationThreadNative.java:763)
11-20 20:29:04.365 19154 19170 E AndroidRuntime:        at com.android.server.am.BroadcastQueue.processCurBroadcastLocked(BroadcastQueue.java:230)
11-20 20:29:04.365 19154 19170 E AndroidRuntime:        at com.android.server.am.BroadcastQueue.processNextBroadcast(BroadcastQueue.java:777)

This is odd because where we do Bundle.writeToParcel(), we are just writing the Parcel
we have with its current length.  There is no way this should be able to fail like this...
unless the Bundle is changed while we are running?

Hm.

It looks like the location manager is holding on to Location objects which have a
Bundle of extras.  It is that Bundle of extras that the crash is happening on.
And the bundle extras can be changed as it operates.  And there are places where
the raw Location object is returned from the location manager, which means the
caller can be olding on to a Location object whose extras can be changed at any
time by other threads in the location manager.

So that seem suspicious.

This change should take care of all these places in the location manager, by
making sure to copy the location object before it goes out of the location
manager.

In addition, add some code to the activity manager to not bring down the entire
system if there is a problem trying to send one of these broadcasts.  There is
no need, we can just skip the broadcast as bad.

Change-Id: I3043c1e06f9d2931a367f831b6a970d71b0d0621
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 7a55497c..0d4a1c2 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -531,7 +531,7 @@
                     synchronized (this) {
                         // synchronize to ensure incrementPendingBroadcastsLocked()
                         // is called before decrementPendingBroadcasts()
-                        mListener.onLocationChanged(location);
+                        mListener.onLocationChanged(new Location(location));
                         // call this after broadcasting so we do not increment
                         // if we throw an exeption.
                         incrementPendingBroadcastsLocked();
@@ -1323,10 +1323,10 @@
                 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
                     Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
                     if (noGPSLocation != null) {
-                        return mLocationFudger.getOrCreate(noGPSLocation);
+                        return new Location(mLocationFudger.getOrCreate(noGPSLocation));
                     }
                 } else {
-                    return location;
+                    return new Location(location);
                 }
             }
             return null;
diff --git a/services/java/com/android/server/am/BroadcastQueue.java b/services/java/com/android/server/am/BroadcastQueue.java
index f9630ae..bada7f0 100644
--- a/services/java/com/android/server/am/BroadcastQueue.java
+++ b/services/java/com/android/server/am/BroadcastQueue.java
@@ -38,6 +38,7 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.util.EventLog;
+import android.util.Log;
 import android.util.Slog;
 
 /**
@@ -779,6 +780,21 @@
                 } catch (RemoteException e) {
                     Slog.w(TAG, "Exception when sending broadcast to "
                           + r.curComponent, e);
+                } catch (RuntimeException e) {
+                    Log.wtf(TAG, "Failed sending broadcast to "
+                            + r.curComponent + " with " + r.intent, e);
+                    // If some unexpected exception happened, just skip
+                    // this broadcast.  At this point we are not in the call
+                    // from a client, so throwing an exception out from here
+                    // will crash the entire system instead of just whoever
+                    // sent the broadcast.
+                    logBroadcastReceiverDiscardLocked(r);
+                    finishReceiverLocked(r, r.resultCode, r.resultData,
+                            r.resultExtras, r.resultAbort, true);
+                    scheduleBroadcastsLocked();
+                    // We need to reset the state if we failed to start the receiver.
+                    r.state = BroadcastRecord.IDLE;
+                    return;
                 }
 
                 // If a dead object exception was thrown -- fall through to