Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f0d6e1c5 authored by Tyler Gunn's avatar Tyler Gunn
Browse files

Catch exceptions when comparing bundles.

We tried to catch ClassCastException in the past and log the key in
question so we could determine the root cause.  It looks like in the end
this is likely a concurrent access issue where the InCallService is
trying to modify the bundle while Telecom is updating it.  This is not
something that happens often.  Rather than taking the performance hit of
copying the Bundle in the get, or sychronizing, we'll just catch and
assume the Bundles are not equal.  Worst case we end up triggering an
extra Call.Callback#onDetailsChanged signal to the ICS.

Test: Run unit tests.
Flag: NONE Crash fix.
Fixes: 404168135
Change-Id: I5bc7a2170701fda364f6c4ca19d82a4c46745792
parent c0e04bd2
Loading
Loading
Loading
Loading
+35 −25
Original line number Original line Diff line number Diff line
@@ -2912,7 +2912,7 @@ public final class Call {
        if (bundle.size() != newBundle.size()) {
        if (bundle.size() != newBundle.size()) {
            return false;
            return false;
        }
        }

        try {
            for (String key : bundle.keySet()) {
            for (String key : bundle.keySet()) {
                if (key != null) {
                if (key != null) {
                    if (!newBundle.containsKey(key)) {
                    if (!newBundle.containsKey(key)) {
@@ -2937,14 +2937,24 @@ public final class Call {
                        }
                        }
                    } catch (BadParcelableException e) {
                    } catch (BadParcelableException e) {
                        return false;
                        return false;
                } catch (ClassCastException e) {
                    Log.e(LOG_TAG, e, "areBundlesEqual: failure comparing bundle key %s", key);
                    // until we know what is causing this, we should rethrow -- this is still not
                    // expected.
                    throw e;
                    }
                    }
                }
                }
            }
            }
        } catch (ClassCastException | ArrayIndexOutOfBoundsException e) {
            // Unfortunately this may get raised when accessing the bundle's keyset, so we cannot
            // determine WHY a class cast exception is happening.  We had tried in the past to do
            // this down in the for loop so we could figure out which key is causing an issue.
            // Bundles are not thread safe, so the most likely issue here is that the InCallService
            // implementation is accessing the Bundle WHILE an incoming Telecom update comes in to
            // potentially replace the Bundle.  We call "areBundlesEqual" to see if the newly
            // unparceled Call.Details is the same as what is already in the current Call instance.
            // If those two operations overleave, I can see the potential for concurrent
            // modification and edit of the Bundle.  So we'll just catch here and assume the Bundles
            // are not the same.  This means a Call.CallBack may fire the onCallDetails changed
            // callback when the Bundle didn't actually change.
            Log.e(LOG_TAG, e, "areBundlesEqual: failed!");
            return false;
        }
        return true;
        return true;
    }
    }
}
}