summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/com/android/incallui/Call.java114
-rw-r--r--tests/src/com/android/incallui/CallTest.java125
2 files changed, 197 insertions, 42 deletions
diff --git a/src/com/android/incallui/Call.java b/src/com/android/incallui/Call.java
index 16a53b29..b768cdd1 100644
--- a/src/com/android/incallui/Call.java
+++ b/src/com/android/incallui/Call.java
@@ -332,48 +332,7 @@ public class Call {
mTelecommCall.getChildren().get(i)).getId());
}
- Bundle callExtras = mTelecommCall.getDetails().getExtras();
- if (callExtras != null) {
- // Check for a change in the child address and notify any listeners.
- if (callExtras.containsKey(Connection.EXTRA_CHILD_ADDRESS)) {
- String childNumber = callExtras.getString(Connection.EXTRA_CHILD_ADDRESS);
-
- if (!Objects.equals(childNumber, mChildNumber)) {
- mChildNumber = childNumber;
- CallList.getInstance().onChildNumberChange(this);
- }
- }
-
- // Last forwarded number comes in as an array of strings. We want to choose the last
- // item in the array. The forwarding numbers arrive independently of when the call is
- // originally set up, so we need to notify the the UI of the change.
- if (callExtras.containsKey(Connection.EXTRA_LAST_FORWARDED_NUMBER)) {
- ArrayList<String> lastForwardedNumbers =
- callExtras.getStringArrayList(Connection.EXTRA_LAST_FORWARDED_NUMBER);
-
- if (lastForwardedNumbers != null) {
- String lastForwardedNumber = null;
- if (!lastForwardedNumbers.isEmpty()) {
- lastForwardedNumber = lastForwardedNumbers.get(
- lastForwardedNumbers.size() - 1);
- }
-
- if (!Objects.equals(lastForwardedNumber, mLastForwardedNumber)) {
- mLastForwardedNumber = lastForwardedNumber;
- CallList.getInstance().onLastForwardedNumberChange(this);
- }
- }
- }
-
- // Call subject is present in the extras at the start of call, so we do not need to
- // notify any other listeners of this.
- if (callExtras.containsKey(Connection.EXTRA_CALL_SUBJECT)) {
- String callSubject = callExtras.getString(Connection.EXTRA_CALL_SUBJECT);
- if (!Objects.equals(mCallSubject, callSubject)) {
- mCallSubject = callSubject;
- }
- }
- }
+ updateFromCallExtras(mTelecommCall.getDetails().getExtras());
// If the handle of the call has changed, update state for the call determining if it is an
// emergency call.
@@ -400,6 +359,77 @@ public class Call {
}
}
+ /**
+ * Tests corruption of the {@code callExtras} bundle by calling {@link
+ * Bundle#containsKey(String)}. If the bundle is corrupted a {@link IllegalArgumentException}
+ * will be thrown and caught by this function.
+ *
+ * @param callExtras the bundle to verify
+ * @returns {@code true} if the bundle is corrupted, {@code false} otherwise.
+ */
+ protected boolean areCallExtrasCorrupted(Bundle callExtras) {
+ /**
+ * There's currently a bug in Telephony service (b/25613098) that could corrupt the
+ * extras bundle, resulting in a IllegalArgumentException while validating data under
+ * {@link Bundle#containsKey(String)}.
+ */
+ try {
+ callExtras.containsKey(Connection.EXTRA_CHILD_ADDRESS);
+ return false;
+ } catch (IllegalArgumentException e) {
+ Log.e(this, "CallExtras is corrupted, ignoring exception", e);
+ return true;
+ }
+ }
+
+ protected void updateFromCallExtras(Bundle callExtras) {
+ if (callExtras == null || areCallExtrasCorrupted(callExtras)) {
+ /**
+ * If the bundle is corrupted, abandon information update as a work around. These are
+ * not critical for the dialer to function.
+ */
+ return;
+ }
+ // Check for a change in the child address and notify any listeners.
+ if (callExtras.containsKey(Connection.EXTRA_CHILD_ADDRESS)) {
+ String childNumber = callExtras.getString(Connection.EXTRA_CHILD_ADDRESS);
+ if (!Objects.equals(childNumber, mChildNumber)) {
+ mChildNumber = childNumber;
+ CallList.getInstance().onChildNumberChange(this);
+ }
+ }
+
+ // Last forwarded number comes in as an array of strings. We want to choose the
+ // last item in the array. The forwarding numbers arrive independently of when the
+ // call is originally set up, so we need to notify the the UI of the change.
+ if (callExtras.containsKey(Connection.EXTRA_LAST_FORWARDED_NUMBER)) {
+ ArrayList<String> lastForwardedNumbers =
+ callExtras.getStringArrayList(Connection.EXTRA_LAST_FORWARDED_NUMBER);
+
+ if (lastForwardedNumbers != null) {
+ String lastForwardedNumber = null;
+ if (!lastForwardedNumbers.isEmpty()) {
+ lastForwardedNumber = lastForwardedNumbers.get(
+ lastForwardedNumbers.size() - 1);
+ }
+
+ if (!Objects.equals(lastForwardedNumber, mLastForwardedNumber)) {
+ mLastForwardedNumber = lastForwardedNumber;
+ CallList.getInstance().onLastForwardedNumberChange(this);
+ }
+ }
+ }
+
+ // Call subject is present in the extras at the start of call, so we do not need to
+ // notify any other listeners of this.
+ if (callExtras.containsKey(Connection.EXTRA_CALL_SUBJECT)) {
+ String callSubject = callExtras.getString(Connection.EXTRA_CALL_SUBJECT);
+ if (!Objects.equals(mCallSubject, callSubject)) {
+ mCallSubject = callSubject;
+ }
+ }
+ }
+
private static int translateState(int state) {
switch (state) {
case android.telecom.Call.STATE_NEW:
diff --git a/tests/src/com/android/incallui/CallTest.java b/tests/src/com/android/incallui/CallTest.java
new file mode 100644
index 00000000..118ec38d
--- /dev/null
+++ b/tests/src/com/android/incallui/CallTest.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.incallui;
+
+import android.os.Bundle;
+import android.telecom.Connection;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+// @formatter:off
+/**
+ * Run test with
+ * adb shell am instrument -e class com.android.incallui.CallTest -w com.google.android.dialer.tests/android.test.InstrumentationTestRunner
+ */
+// @formatter:on
+
+@SmallTest
+public class CallTest extends AndroidTestCase {
+
+ private TestCall mCall;
+
+ private final static String CHILD_NUMBER = "123";
+ private final static ArrayList<String> LAST_FORWARDED_NUMBER_LIST =
+ new ArrayList(Arrays.asList("456", "789"));
+ private final static String LAST_FORWARDED_NUMBER = "789";
+ private final static String CALL_SUBJECT = "foo";
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+
+ mCall = new TestCall();
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testUpdateFromCallExtras() {
+ mCall.updateFromCallExtras(getTestBundle());
+ verifyTestBundleResult();
+ }
+
+ public void testUpdateFromCallExtras_corruptedBundle() {
+ mCall.setBundleCorrupted(true);
+ mCall.updateFromCallExtras(getTestBundle());
+
+ assertEquals(mCall.getChildNumber(), null);
+ assertEquals(mCall.getLastForwardedNumber(), null);
+ assertEquals(mCall.getCallSubject(), null);
+ }
+
+ public void testUpdateFromCallExtras_corruptedBundleOverwrite() {
+
+ mCall.updateFromCallExtras(getTestBundle());
+ mCall.setBundleCorrupted(true);
+ Bundle bundle = new Bundle();
+ bundle.putString(Connection.EXTRA_CHILD_ADDRESS, "321");
+ bundle.putStringArrayList(Connection.EXTRA_LAST_FORWARDED_NUMBER,
+ new ArrayList(Arrays.asList("654", "987")));
+ bundle.putString(Connection.EXTRA_CALL_SUBJECT, "bar");
+ mCall.updateFromCallExtras(bundle);
+ //corrupted bundle should not overwrite existing values.
+ verifyTestBundleResult();
+ }
+
+ private Bundle getTestBundle() {
+ Bundle bundle = new Bundle();
+ bundle.putString(Connection.EXTRA_CHILD_ADDRESS, CHILD_NUMBER);
+ bundle.putStringArrayList(Connection.EXTRA_LAST_FORWARDED_NUMBER,
+ LAST_FORWARDED_NUMBER_LIST);
+ bundle.putString(Connection.EXTRA_CALL_SUBJECT, CALL_SUBJECT);
+ return bundle;
+ }
+
+ private void verifyTestBundleResult() {
+ assertEquals(CHILD_NUMBER, mCall.getChildNumber());
+ assertEquals(LAST_FORWARDED_NUMBER, mCall.getLastForwardedNumber());
+ assertEquals(CALL_SUBJECT, mCall.getCallSubject());
+ }
+
+ private class TestCall extends Call {
+
+ private boolean mBundleCorrupted = false;
+
+ public TestCall() {
+ super(Call.State.NEW);
+ }
+
+ @Override
+ public void updateFromCallExtras(Bundle bundle) {
+ super.updateFromCallExtras(bundle);
+ }
+
+ public void setBundleCorrupted(boolean value) {
+ this.mBundleCorrupted = value;
+ }
+
+ @Override
+ protected boolean areCallExtrasCorrupted(Bundle callExtras) {
+ if (mBundleCorrupted) {
+ return true;
+ }
+ return super.areCallExtrasCorrupted(callExtras);
+ }
+ }
+}