summaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
authorTreehugger Robot <treehugger-gerrit@google.com>2017-10-17 16:52:28 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2017-10-17 16:52:28 +0000
commit0d1362b28afb4a71b8b2a56bad2be3fcf2802de6 (patch)
tree91fb2d0f5c065f024a7332ec664c794cdf30f413 /java
parent5a6cb962ae30ad9e308b5bcc00920daf84618808 (diff)
parentc114cce52656e6ace2ffdfd075b0e8cd140cd498 (diff)
Merge changes I84ec0ac5,I2b92e1e0,Ic30fa6c6
* changes: Move Duo related constants out of interface Dismissing location prompt now actually prevents it from reshowing. Add GSM conference calling to simulator.
Diffstat (limited to 'java')
-rw-r--r--java/com/android/dialer/app/calllog/CallLogAdapter.java17
-rw-r--r--java/com/android/dialer/app/calllog/CallLogGroupBuilder.java7
-rw-r--r--java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java13
-rw-r--r--java/com/android/dialer/app/calllog/MissedCallNotifier.java6
-rw-r--r--java/com/android/dialer/calllogutils/CallbackActionHelper.java20
-rw-r--r--java/com/android/dialer/duo/Duo.java14
-rw-r--r--java/com/android/dialer/duo/DuoConstants.java38
-rw-r--r--java/com/android/dialer/duo/stub/DuoStub.java20
-rw-r--r--java/com/android/dialer/searchfragment/list/NewSearchFragment.java10
-rw-r--r--java/com/android/dialer/searchfragment/list/SearchAdapter.java2
-rw-r--r--java/com/android/dialer/simulator/Simulator.java20
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorConference.java168
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorConferenceCreator.java229
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorConnection.java6
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorConnectionService.java20
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorMissedCallCreator.java4
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorSimCallManager.java43
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorSpamCallCreator.java4
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorVideoCall.java11
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorVoiceCall.java30
20 files changed, 580 insertions, 102 deletions
diff --git a/java/com/android/dialer/app/calllog/CallLogAdapter.java b/java/com/android/dialer/app/calllog/CallLogAdapter.java
index 679901e9f..016bce322 100644
--- a/java/com/android/dialer/app/calllog/CallLogAdapter.java
+++ b/java/com/android/dialer/app/calllog/CallLogAdapter.java
@@ -75,6 +75,7 @@ import com.android.dialer.compat.android.provider.VoicemailCompat;
import com.android.dialer.configprovider.ConfigProviderBindings;
import com.android.dialer.duo.Duo;
import com.android.dialer.duo.DuoComponent;
+import com.android.dialer.duo.DuoConstants;
import com.android.dialer.duo.DuoListener;
import com.android.dialer.enrichedcall.EnrichedCallCapabilities;
import com.android.dialer.enrichedcall.EnrichedCallComponent;
@@ -399,11 +400,7 @@ public class CallLogAdapter extends GroupingListAdapter
if (intentProvider == null) {
return false;
}
- String packageName = DuoComponent.get(mActivity).getDuo().getPackageName();
- if (packageName == null) {
- return false;
- }
- return packageName.equals(intentProvider.getIntent(mActivity).getPackage());
+ return DuoConstants.PACKAGE_NAME.equals(intentProvider.getIntent(mActivity).getPackage());
}
};
@@ -697,7 +694,7 @@ public class CallLogAdapter extends GroupingListAdapter
@Override
protected void addGroups(Cursor cursor) {
- mCallLogGroupBuilder.addGroups(cursor, mActivity);
+ mCallLogGroupBuilder.addGroups(cursor);
}
@Override
@@ -981,11 +978,9 @@ public class CallLogAdapter extends GroupingListAdapter
.setFeatures(cursor.getInt(CallLogQuery.FEATURES));
String phoneAccountComponentName = cursor.getString(CallLogQuery.ACCOUNT_COMPONENT_NAME);
- if (getDuo().getPhoneAccountComponentName() != null
- && getDuo()
- .getPhoneAccountComponentName()
- .flattenToString()
- .equals(phoneAccountComponentName)) {
+ if (DuoConstants.PHONE_ACCOUNT_COMPONENT_NAME
+ .flattenToString()
+ .equals(phoneAccountComponentName)) {
entry.setIsDuoCall(true);
}
diff --git a/java/com/android/dialer/app/calllog/CallLogGroupBuilder.java b/java/com/android/dialer/app/calllog/CallLogGroupBuilder.java
index 57a8be730..513c8aa59 100644
--- a/java/com/android/dialer/app/calllog/CallLogGroupBuilder.java
+++ b/java/com/android/dialer/app/calllog/CallLogGroupBuilder.java
@@ -16,7 +16,6 @@
package com.android.dialer.app.calllog;
-import android.content.Context;
import android.database.Cursor;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
@@ -74,7 +73,7 @@ public class CallLogGroupBuilder {
*
* @see GroupingListAdapter#addGroups(Cursor)
*/
- public void addGroups(Cursor cursor, Context context) {
+ public void addGroups(Cursor cursor) {
final int count = cursor.getCount();
if (count == 0) {
return;
@@ -99,7 +98,7 @@ public class CallLogGroupBuilder {
int groupFeatures = cursor.getInt(CallLogQuery.FEATURES);
int groupCallbackAction =
CallbackActionHelper.getCallbackAction(
- groupNumber, groupFeatures, groupAccountComponentName, context);
+ groupNumber, groupFeatures, groupAccountComponentName);
mGroupCreator.setCallbackAction(firstRowId, groupCallbackAction);
// Instantiate other group values to those of the first call in the cursor.
@@ -134,7 +133,7 @@ public class CallLogGroupBuilder {
accountComponentName = cursor.getString(CallLogQuery.ACCOUNT_COMPONENT_NAME);
accountId = cursor.getString(CallLogQuery.ACCOUNT_ID);
callbackAction =
- CallbackActionHelper.getCallbackAction(number, features, accountComponentName, context);
+ CallbackActionHelper.getCallbackAction(number, features, accountComponentName);
final boolean isSameNumber = equalNumbers(groupNumber, number);
final boolean isSamePostDialDigits = groupPostDialDigits.equals(numberPostDialDigits);
diff --git a/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java b/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java
index f0852bdb5..d5dfb06dc 100644
--- a/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java
+++ b/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java
@@ -27,7 +27,6 @@ import android.provider.CallLog;
import android.provider.CallLog.Calls;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.support.annotation.IntDef;
-import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
import android.support.v7.widget.CardView;
@@ -75,8 +74,7 @@ import com.android.dialer.constants.ActivityRequestCodes;
import com.android.dialer.contactphoto.ContactPhotoManager;
import com.android.dialer.dialercontact.DialerContact;
import com.android.dialer.dialercontact.SimDetails;
-import com.android.dialer.duo.Duo;
-import com.android.dialer.duo.DuoComponent;
+import com.android.dialer.duo.DuoConstants;
import com.android.dialer.lettertile.LetterTileDrawable;
import com.android.dialer.lettertile.LetterTileDrawable.ContactType;
import com.android.dialer.logging.ContactSource;
@@ -746,7 +744,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder
private boolean showDuoPrimaryButton() {
return accountHandle != null
- && accountHandle.getComponentName().equals(getDuo().getPhoneAccountComponentName())
+ && accountHandle.getComponentName().equals(DuoConstants.PHONE_ACCOUNT_COMPONENT_NAME)
&& duoReady;
}
@@ -961,7 +959,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder
// We check to see if we are starting a Duo intent. The reason is Duo
// intents need to be started using startActivityForResult instead of the usual startActivity
String packageName = intent.getPackage();
- if (packageName != null && packageName.equals(getDuo().getPackageName())) {
+ if (DuoConstants.PACKAGE_NAME.equals(packageName)) {
Logger.get(mContext)
.logImpression(DialerImpression.Type.LIGHTBRINGER_VIDEO_REQUESTED_FROM_CALL_LOG);
if (isNonContactEntry(info)) {
@@ -1125,11 +1123,6 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder
return callDetailsEntries;
}
- @NonNull
- private Duo getDuo() {
- return DuoComponent.get(mContext).getDuo();
- }
-
@Override
public void onCreateContextMenu(
final ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
diff --git a/java/com/android/dialer/app/calllog/MissedCallNotifier.java b/java/com/android/dialer/app/calllog/MissedCallNotifier.java
index f50751e2b..fff68d4c4 100644
--- a/java/com/android/dialer/app/calllog/MissedCallNotifier.java
+++ b/java/com/android/dialer/app/calllog/MissedCallNotifier.java
@@ -53,6 +53,7 @@ import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import com.android.dialer.common.concurrent.DialerExecutor.Worker;
import com.android.dialer.compat.android.provider.VoicemailCompat;
+import com.android.dialer.duo.DuoConstants;
import com.android.dialer.enrichedcall.FuzzyPhoneNumberMatcher;
import com.android.dialer.notification.DialerNotificationManager;
import com.android.dialer.notification.NotificationChannelId;
@@ -253,6 +254,7 @@ public class MissedCallNotifier implements Worker<Pair<Integer, String>, Void> {
if (newCalls == null) {
return;
}
+
TelecomManager telecomManager = context.getSystemService(TelecomManager.class);
Iterator<NewCall> iterator = newCalls.iterator();
while (iterator.hasNext()) {
@@ -269,6 +271,10 @@ public class MissedCallNotifier implements Worker<Pair<Integer, String>, Void> {
if (phoneAccount == null) {
continue;
}
+ if (DuoConstants.PHONE_ACCOUNT_HANDLE.equals(phoneAccountHandle)) {
+ iterator.remove();
+ continue;
+ }
if (phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)) {
LogUtil.i(
"MissedCallNotifier.removeSelfManagedCalls",
diff --git a/java/com/android/dialer/calllogutils/CallbackActionHelper.java b/java/com/android/dialer/calllogutils/CallbackActionHelper.java
index 304994305..1e219f144 100644
--- a/java/com/android/dialer/calllogutils/CallbackActionHelper.java
+++ b/java/com/android/dialer/calllogutils/CallbackActionHelper.java
@@ -16,12 +16,10 @@
package com.android.dialer.calllogutils;
-import android.content.Context;
import android.provider.CallLog.Calls;
import android.support.annotation.IntDef;
import android.text.TextUtils;
-import com.android.dialer.duo.Duo;
-import com.android.dialer.duo.DuoComponent;
+import com.android.dialer.duo.DuoConstants;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -45,12 +43,11 @@ public class CallbackActionHelper {
* @param features Value of features in column {@link android.provider.CallLog.Calls#FEATURES}.
* @param phoneAccountComponentName Account name in column {@link
* android.provider.CallLog.Calls#PHONE_ACCOUNT_COMPONENT_NAME}.
- * @param context The context in which the method is called.
* @return One of the values in {@link CallbackAction}
*/
public static @CallbackAction int getCallbackAction(
- String number, int features, String phoneAccountComponentName, Context context) {
- return getCallbackAction(number, features, isDuoCall(phoneAccountComponentName, context));
+ String number, int features, String phoneAccountComponentName) {
+ return getCallbackAction(number, features, isDuoCall(phoneAccountComponentName));
}
/**
@@ -78,12 +75,9 @@ public class CallbackActionHelper {
return CallbackAction.VOICE;
}
- private static boolean isDuoCall(String phoneAccountComponentName, Context context) {
- Duo lightBringer = DuoComponent.get(context).getDuo();
- return lightBringer.getPhoneAccountComponentName() != null
- && lightBringer
- .getPhoneAccountComponentName()
- .flattenToString()
- .equals(phoneAccountComponentName);
+ private static boolean isDuoCall(String phoneAccountComponentName) {
+ return DuoConstants.PHONE_ACCOUNT_COMPONENT_NAME
+ .flattenToString()
+ .equals(phoneAccountComponentName);
}
}
diff --git a/java/com/android/dialer/duo/Duo.java b/java/com/android/dialer/duo/Duo.java
index ec07ad4b4..839c1d3a8 100644
--- a/java/com/android/dialer/duo/Duo.java
+++ b/java/com/android/dialer/duo/Duo.java
@@ -16,7 +16,6 @@
package com.android.dialer.duo;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.support.annotation.MainThread;
@@ -24,7 +23,6 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.telecom.Call;
-import android.telecom.PhoneAccountHandle;
import com.google.auto.value.AutoValue;
import com.google.common.base.Optional;
import java.util.List;
@@ -55,18 +53,6 @@ public interface Duo {
@MainThread
void unregisterListener(@NonNull DuoListener listener);
- @Nullable
- @MainThread
- ComponentName getPhoneAccountComponentName();
-
- @Nullable
- @MainThread
- PhoneAccountHandle getPhoneAccountHandle();
-
- @Nullable
- @MainThread
- String getPackageName();
-
@StringRes
@MainThread
int getOutgoingCallTypeText();
diff --git a/java/com/android/dialer/duo/DuoConstants.java b/java/com/android/dialer/duo/DuoConstants.java
new file mode 100644
index 000000000..50254ee13
--- /dev/null
+++ b/java/com/android/dialer/duo/DuoConstants.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2017 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.dialer.duo;
+
+import android.content.ComponentName;
+import android.telecom.PhoneAccountHandle;
+
+/** Constants to reference the Duo application. */
+public final class DuoConstants {
+ public static final String PACKAGE_NAME = "com.google.android.apps.tachyon";
+
+ public static final String CONNECTION_SERVICE =
+ "com.google.android.apps.tachyon.telecom.TachyonTelecomConnectionService";
+
+ public static final String PHONE_ACCOUNT_ID = "0";
+
+ public static final ComponentName PHONE_ACCOUNT_COMPONENT_NAME =
+ new ComponentName(PACKAGE_NAME, CONNECTION_SERVICE);
+
+ public static final PhoneAccountHandle PHONE_ACCOUNT_HANDLE =
+ new PhoneAccountHandle(PHONE_ACCOUNT_COMPONENT_NAME, PHONE_ACCOUNT_ID);
+
+ private DuoConstants() {}
+}
diff --git a/java/com/android/dialer/duo/stub/DuoStub.java b/java/com/android/dialer/duo/stub/DuoStub.java
index 99f03adfd..82b9c79e3 100644
--- a/java/com/android/dialer/duo/stub/DuoStub.java
+++ b/java/com/android/dialer/duo/stub/DuoStub.java
@@ -16,7 +16,6 @@
package com.android.dialer.duo.stub;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.support.annotation.MainThread;
@@ -24,7 +23,6 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.telecom.Call;
-import android.telecom.PhoneAccountHandle;
import com.android.dialer.common.Assert;
import com.android.dialer.duo.Duo;
import com.android.dialer.duo.DuoListener;
@@ -95,24 +93,6 @@ public class DuoStub implements Duo {
Assert.isNotNull(listener);
}
- @Nullable
- @Override
- public ComponentName getPhoneAccountComponentName() {
- return null;
- }
-
- @Nullable
- @Override
- public PhoneAccountHandle getPhoneAccountHandle() {
- return null;
- }
-
- @Nullable
- @Override
- public String getPackageName() {
- return null;
- }
-
@StringRes
@Override
public int getOutgoingCallTypeText() {
diff --git a/java/com/android/dialer/searchfragment/list/NewSearchFragment.java b/java/com/android/dialer/searchfragment/list/NewSearchFragment.java
index 393b07a6b..6115c2f1c 100644
--- a/java/com/android/dialer/searchfragment/list/NewSearchFragment.java
+++ b/java/com/android/dialer/searchfragment/list/NewSearchFragment.java
@@ -345,7 +345,7 @@ public final class NewSearchFragment extends Fragment
if (!PermissionsUtil.hasLocationPermissions(getContext())
&& !DialerUtils.getDefaultSharedPreferenceForDeviceProtectedStorageContext(getContext())
.getBoolean(KEY_LOCATION_PROMPT_DISMISSED, false)) {
- if (adapter != null && isRegularSearch()) {
+ if (adapter != null && isRegularSearch() && !hasBeenDismissed()) {
adapter.showLocationPermissionRequest(
v -> requestLocationPermission(), v -> dismissLocationPermission());
}
@@ -372,7 +372,8 @@ public final class NewSearchFragment extends Fragment
requestPermissions(deniedPermissions, LOCATION_PERMISSION_REQUEST_CODE);
}
- private void dismissLocationPermission() {
+ @VisibleForTesting
+ public void dismissLocationPermission() {
PreferenceManager.getDefaultSharedPreferences(getContext())
.edit()
.putBoolean(KEY_LOCATION_PROMPT_DISMISSED, true)
@@ -380,6 +381,11 @@ public final class NewSearchFragment extends Fragment
adapter.hideLocationPermissionRequest();
}
+ private boolean hasBeenDismissed() {
+ return PreferenceManager.getDefaultSharedPreferences(getContext())
+ .getBoolean(KEY_LOCATION_PROMPT_DISMISSED, false);
+ }
+
@Override
public void onResume() {
super.onResume();
diff --git a/java/com/android/dialer/searchfragment/list/SearchAdapter.java b/java/com/android/dialer/searchfragment/list/SearchAdapter.java
index 29e4e2320..949c2a2c5 100644
--- a/java/com/android/dialer/searchfragment/list/SearchAdapter.java
+++ b/java/com/android/dialer/searchfragment/list/SearchAdapter.java
@@ -187,7 +187,7 @@ public final class SearchAdapter extends RecyclerView.Adapter<ViewHolder>
this.allowClickListener = Assert.isNotNull(allowClickListener);
this.dismissClickListener = Assert.isNotNull(dismissClickListener);
if (searchCursorManager.showLocationPermissionRequest(true)) {
- notifyItemRemoved(0);
+ notifyItemInserted(0);
}
}
diff --git a/java/com/android/dialer/simulator/Simulator.java b/java/com/android/dialer/simulator/Simulator.java
index f753e5f6b..4812fa5d6 100644
--- a/java/com/android/dialer/simulator/Simulator.java
+++ b/java/com/android/dialer/simulator/Simulator.java
@@ -30,6 +30,16 @@ public interface Simulator {
ActionProvider getActionProvider(Context context);
+ /** The type of conference to emulate. */
+ // TODO(b/67785540): add VoLTE and CDMA conference call
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ CONFERENCE_TYPE_GSM,
+ })
+ @interface ConferenceType {}
+
+ static final int CONFERENCE_TYPE_GSM = 1;
+
/** Information about a connection event. */
public static class Event {
/** The type of connection event. */
@@ -44,6 +54,11 @@ public interface Simulator {
STATE_CHANGE,
DTMF,
SESSION_MODIFY_REQUEST,
+ CALL_AUDIO_STATE_CHANGED,
+ CONNECTION_ADDED,
+ MERGE,
+ SEPARATE,
+ SWAP,
})
public @interface Type {}
@@ -56,6 +71,11 @@ public interface Simulator {
public static final int STATE_CHANGE = 6;
public static final int DTMF = 7;
public static final int SESSION_MODIFY_REQUEST = 8;
+ public static final int CALL_AUDIO_STATE_CHANGED = 9;
+ public static final int CONNECTION_ADDED = 10;
+ public static final int MERGE = 11;
+ public static final int SEPARATE = 12;
+ public static final int SWAP = 13;
@Type public final int type;
/** Holds event specific information. For example, for DTMF this could be the keycode. */
diff --git a/java/com/android/dialer/simulator/impl/SimulatorConference.java b/java/com/android/dialer/simulator/impl/SimulatorConference.java
new file mode 100644
index 000000000..7468b56b5
--- /dev/null
+++ b/java/com/android/dialer/simulator/impl/SimulatorConference.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2017 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.dialer.simulator.impl;
+
+import android.support.annotation.NonNull;
+import android.telecom.CallAudioState;
+import android.telecom.Conference;
+import android.telecom.Connection;
+import android.telecom.PhoneAccountHandle;
+import com.android.dialer.common.Assert;
+import com.android.dialer.common.LogUtil;
+import com.android.dialer.simulator.Simulator;
+import com.android.dialer.simulator.Simulator.Event;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Represents a conference call. When a user merges two phone calls we create an instance of this
+ * conference object and add it to the connection service. All operations such as hold and DTMF are
+ * then performed on this object.
+ */
+public final class SimulatorConference extends Conference implements SimulatorConnection.Listener {
+ static final int PROPERTY_GENERIC_CONFERENCE = 1 << 1;
+
+ private final List<Listener> listeners = new ArrayList<>();
+ private final List<Event> events = new ArrayList<>();
+ private final int conferenceType;
+
+ private SimulatorConference(
+ PhoneAccountHandle handle, @Simulator.ConferenceType int conferenceType) {
+ super(handle);
+ this.conferenceType = conferenceType;
+ setActive();
+ }
+
+ static SimulatorConference newGsmConference(PhoneAccountHandle handle) {
+ SimulatorConference simulatorConference =
+ new SimulatorConference(handle, Simulator.CONFERENCE_TYPE_GSM);
+ simulatorConference.setConnectionCapabilities(
+ Connection.CAPABILITY_MUTE
+ | Connection.CAPABILITY_SUPPORT_HOLD
+ | Connection.CAPABILITY_HOLD
+ | Connection.CAPABILITY_MANAGE_CONFERENCE);
+ return simulatorConference;
+ }
+
+ public void addListener(@NonNull Listener listener) {
+ listeners.add(Assert.isNotNull(listener));
+ }
+
+ public void removeListener(@NonNull Listener listener) {
+ listeners.remove(Assert.isNotNull(listener));
+ }
+
+ @NonNull
+ public List<Event> getEvents() {
+ return events;
+ }
+
+ @Override
+ public void onCallAudioStateChanged(CallAudioState state) {
+ LogUtil.enterBlock("SimulatorConference.onCallAudioStateChanged");
+ onEvent(new Event(Event.CALL_AUDIO_STATE_CHANGED));
+ }
+
+ @Override
+ public void onConnectionAdded(Connection connection) {
+ LogUtil.enterBlock("SimulatorConference.onConnectionAdded");
+ onEvent(
+ new Event(
+ Event.CONNECTION_ADDED, SimulatorSimCallManager.getConnectionTag(connection), null));
+ ((SimulatorConnection) connection).addListener(this);
+ }
+
+ @Override
+ public void onDisconnect() {
+ LogUtil.enterBlock("SimulatorConference.onDisconnect");
+ onEvent(new Event(Event.DISCONNECT));
+ }
+
+ @Override
+ public void onHold() {
+ LogUtil.enterBlock("SimulatorConference.onHold");
+ onEvent(new Event(Event.HOLD));
+ }
+
+ @Override
+ public void onMerge(Connection connection) {
+ LogUtil.i("SimulatorConference.onMerge", "connection: " + connection);
+ onEvent(new Event(Event.MERGE, SimulatorSimCallManager.getConnectionTag(connection), null));
+ }
+
+ @Override
+ public void onMerge() {
+ LogUtil.enterBlock("SimulatorConference.onMerge");
+ onEvent(new Event(Event.MERGE));
+ }
+
+ @Override
+ public void onPlayDtmfTone(char c) {
+ LogUtil.enterBlock("SimulatorConference.onPlayDtmfTone");
+ onEvent(new Event(Event.DTMF, Character.toString(c), null));
+ }
+
+ @Override
+ public void onSeparate(Connection connection) {
+ LogUtil.i("SimulatorConference.onSeparate", "connection: " + connection);
+ onEvent(new Event(Event.SEPARATE, SimulatorSimCallManager.getConnectionTag(connection), null));
+ }
+
+ @Override
+ public void onSwap() {
+ LogUtil.enterBlock("SimulatorConference.onSwap");
+ onEvent(new Event(Event.SWAP));
+ }
+
+ @Override
+ public void onUnhold() {
+ LogUtil.enterBlock("SimulatorConference.onUnhold");
+ onEvent(new Event(Event.UNHOLD));
+ }
+
+ @Override
+ public void onEvent(@NonNull SimulatorConnection connection, @NonNull Event event) {
+ if (conferenceType == Simulator.CONFERENCE_TYPE_GSM) {
+ onGsmEvent(connection, event);
+ }
+ }
+
+ private void onGsmEvent(@NonNull SimulatorConnection connection, @NonNull Event event) {
+ if (event.type == Event.STATE_CHANGE
+ && Connection.stateToString(Connection.STATE_DISCONNECTED).equals(event.data2)) {
+ removeConnection(connection);
+ connection.removeListener(this);
+ if (getConnections().size() <= 1) {
+ // When only one connection exists, it's not conference call anymore
+ setDisconnected(connection.getDisconnectCause());
+ destroy();
+ }
+ }
+ }
+
+ void onEvent(@NonNull Event event) {
+ events.add(Assert.isNotNull(event));
+ for (Listener listener : new ArrayList<>(listeners)) {
+ listener.onEvent(this, event);
+ }
+ }
+
+ /** Callback for when a new event arrives. */
+ public interface Listener {
+ void onEvent(@NonNull SimulatorConference conference, @NonNull Event event);
+ }
+}
diff --git a/java/com/android/dialer/simulator/impl/SimulatorConferenceCreator.java b/java/com/android/dialer/simulator/impl/SimulatorConferenceCreator.java
new file mode 100644
index 000000000..838b58dc2
--- /dev/null
+++ b/java/com/android/dialer/simulator/impl/SimulatorConferenceCreator.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2017 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.dialer.simulator.impl;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.telecom.Conferenceable;
+import android.telecom.Connection;
+import android.telecom.DisconnectCause;
+import com.android.dialer.common.Assert;
+import com.android.dialer.common.LogUtil;
+import com.android.dialer.common.concurrent.ThreadUtil;
+import com.android.dialer.simulator.Simulator;
+import com.android.dialer.simulator.Simulator.Event;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+/** Creates a conference with a given number of participants. */
+final class SimulatorConferenceCreator
+ implements SimulatorConnectionService.Listener,
+ SimulatorConnection.Listener,
+ SimulatorConference.Listener {
+ private static final String EXTRA_CALL_COUNT = "call_count";
+
+ @NonNull private final Context context;
+ @NonNull private final List<String> connectionTags = new ArrayList<>();
+ @Simulator.ConferenceType private final int conferenceType;
+
+ public SimulatorConferenceCreator(
+ @NonNull Context context, @Simulator.ConferenceType int conferenceType) {
+ this.context = Assert.isNotNull(context);
+ this.conferenceType = conferenceType;
+ }
+
+ void start(int callCount) {
+ SimulatorConnectionService.addListener(this);
+ addNextCall(callCount);
+ }
+
+ private void addNextCall(int callCount) {
+ LogUtil.i("SimulatorConferenceCreator.addNextIncomingCall", "callCount: " + callCount);
+ if (callCount <= 0) {
+ LogUtil.i("SimulatorConferenceCreator.addNextCall", "done adding calls");
+ return;
+ }
+
+ String callerId = String.format(Locale.US, "+1-650-234%04d", callCount);
+ Bundle extras = new Bundle();
+ extras.putInt(EXTRA_CALL_COUNT, callCount - 1);
+ connectionTags.add(
+ SimulatorSimCallManager.addNewIncomingCall(context, callerId, false /* isVideo */, extras));
+ }
+
+ @Override
+ public void onNewIncomingConnection(@NonNull SimulatorConnection connection) {
+ if (!isMyConnection(connection)) {
+ LogUtil.i("SimulatorConferenceCreator.onNewOutgoingConnection", "unknown connection");
+ return;
+ }
+
+ LogUtil.i("SimulatorConferenceCreator.onNewOutgoingConnection", "connection created");
+ connection.addListener(this);
+
+ // Telecom will force the connection to switch to DIALING when we return it. Wait until after
+ // we're returned it before changing call state.
+ ThreadUtil.postOnUiThread(() -> connection.setActive());
+
+ // Once the connection is active, go ahead and conference it and add the next call.
+ ThreadUtil.postDelayedOnUiThread(
+ () -> {
+ SimulatorConference conference = findCurrentConference();
+ if (conference == null) {
+ Assert.checkArgument(conferenceType == Simulator.CONFERENCE_TYPE_GSM);
+ conference =
+ SimulatorConference.newGsmConference(
+ SimulatorSimCallManager.getSystemPhoneAccountHandle(context));
+ conference.addListener(this);
+ SimulatorConnectionService.getInstance().addConference(conference);
+ }
+ updateConferenceableConnections();
+ conference.addConnection(connection);
+ addNextCall(getCallCount(connection));
+ },
+ 1000);
+ }
+
+ @Override
+ public void onNewOutgoingConnection(@NonNull SimulatorConnection connection) {}
+
+ /**
+ * This is called when the user clicks the merge button. We create the initial conference
+ * automatically but with this method we can let the user split and merge calls as desired.
+ */
+ @Override
+ public void onConference(
+ @NonNull SimulatorConnection connection1, @NonNull SimulatorConnection connection2) {
+ LogUtil.enterBlock("SimulatorConferenceCreator.onConference");
+ if (!isMyConnection(connection1) || !isMyConnection(connection2)) {
+ LogUtil.i("SimulatorConferenceCreator.onConference", "unknown connections, ignoring");
+ return;
+ }
+
+ if (connection1.getConference() != null) {
+ connection1.getConference().addConnection(connection2);
+ } else if (connection2.getConference() != null) {
+ connection2.getConference().addConnection(connection1);
+ } else {
+ Assert.checkArgument(conferenceType == Simulator.CONFERENCE_TYPE_GSM);
+ SimulatorConference conference =
+ SimulatorConference.newGsmConference(
+ SimulatorSimCallManager.getSystemPhoneAccountHandle(context));
+ conference.addConnection(connection1);
+ conference.addConnection(connection2);
+ conference.addListener(this);
+ SimulatorConnectionService.getInstance().addConference(conference);
+ }
+ }
+
+ private boolean isMyConnection(@NonNull Connection connection) {
+ for (String connectionTag : connectionTags) {
+ if (connection.getExtras().getBoolean(connectionTag)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void updateConferenceableConnections() {
+ LogUtil.enterBlock("SimulatorConferenceCreator.updateConferenceableConnections");
+ for (String connectionTag : connectionTags) {
+ SimulatorConnection connection = SimulatorSimCallManager.findConnectionByTag(connectionTag);
+ List<Conferenceable> conferenceables = getMyConferenceables();
+ conferenceables.remove(connection);
+ conferenceables.remove(connection.getConference());
+ connection.setConferenceables(conferenceables);
+ }
+ }
+
+ private List<Conferenceable> getMyConferenceables() {
+ List<Conferenceable> conferenceables = new ArrayList<>();
+ for (String connectionTag : connectionTags) {
+ SimulatorConnection connection = SimulatorSimCallManager.findConnectionByTag(connectionTag);
+ conferenceables.add(connection);
+ if (connection.getConference() != null
+ && !conferenceables.contains(connection.getConference())) {
+ conferenceables.add(connection.getConference());
+ }
+ }
+ return conferenceables;
+ }
+
+ @Nullable
+ private SimulatorConference findCurrentConference() {
+ for (String connectionTag : connectionTags) {
+ SimulatorConnection connection = SimulatorSimCallManager.findConnectionByTag(connectionTag);
+ if (connection.getConference() != null) {
+ return (SimulatorConference) connection.getConference();
+ }
+ }
+ return null;
+ }
+
+ private static int getCallCount(@NonNull Connection connection) {
+ return connection.getExtras().getInt(EXTRA_CALL_COUNT);
+ }
+
+ @Override
+ public void onEvent(@NonNull SimulatorConnection connection, @NonNull Event event) {
+ switch (event.type) {
+ case Event.NONE:
+ throw Assert.createIllegalStateFailException();
+ case Event.HOLD:
+ connection.setOnHold();
+ break;
+ case Event.UNHOLD:
+ connection.setActive();
+ break;
+ case Event.DISCONNECT:
+ connection.setDisconnected(new DisconnectCause(DisconnectCause.LOCAL));
+ break;
+ default:
+ LogUtil.i(
+ "SimulatorConferenceCreator.onEvent", "unexpected conference event: " + event.type);
+ break;
+ }
+ }
+
+ @Override
+ public void onEvent(@NonNull SimulatorConference conference, @NonNull Event event) {
+ switch (event.type) {
+ case Event.MERGE:
+ int capabilities = conference.getConnectionCapabilities();
+ capabilities |= Connection.CAPABILITY_SWAP_CONFERENCE;
+ conference.setConnectionCapabilities(capabilities);
+ break;
+ case Event.SEPARATE:
+ SimulatorConnection connectionToRemove =
+ SimulatorSimCallManager.findConnectionByTag(event.data1);
+ conference.removeConnection(connectionToRemove);
+ break;
+ case Event.DISCONNECT:
+ for (Connection connection : new ArrayList<>(conference.getConnections())) {
+ connection.setDisconnected(new DisconnectCause(DisconnectCause.LOCAL));
+ }
+ break;
+ default:
+ LogUtil.i(
+ "SimulatorConferenceCreator.onEvent", "unexpected conference event: " + event.type);
+ break;
+ }
+ }
+}
diff --git a/java/com/android/dialer/simulator/impl/SimulatorConnection.java b/java/com/android/dialer/simulator/impl/SimulatorConnection.java
index 70c1095dc..e4a34b51b 100644
--- a/java/com/android/dialer/simulator/impl/SimulatorConnection.java
+++ b/java/com/android/dialer/simulator/impl/SimulatorConnection.java
@@ -41,7 +41,9 @@ public final class SimulatorConnection extends Connection {
CAPABILITY_MUTE
| CAPABILITY_SUPPORT_HOLD
| CAPABILITY_HOLD
- | CAPABILITY_CAN_UPGRADE_TO_VIDEO);
+ | CAPABILITY_CAN_UPGRADE_TO_VIDEO
+ | CAPABILITY_DISCONNECT_FROM_CONFERENCE
+ | CAPABILITY_SEPARATE_FROM_CONFERENCE);
setVideoProvider(new SimulatorVideoProvider(context, this));
}
@@ -108,7 +110,7 @@ public final class SimulatorConnection extends Connection {
void onEvent(@NonNull Event event) {
events.add(Assert.isNotNull(event));
- for (Listener listener : listeners) {
+ for (Listener listener : new ArrayList<>(listeners)) {
listener.onEvent(this, event);
}
}
diff --git a/java/com/android/dialer/simulator/impl/SimulatorConnectionService.java b/java/com/android/dialer/simulator/impl/SimulatorConnectionService.java
index 25d4a7240..465890cf0 100644
--- a/java/com/android/dialer/simulator/impl/SimulatorConnectionService.java
+++ b/java/com/android/dialer/simulator/impl/SimulatorConnectionService.java
@@ -109,6 +109,19 @@ public class SimulatorConnectionService extends ConnectionService {
return connection;
}
+ @Override
+ public void onConference(Connection connection1, Connection connection2) {
+ LogUtil.i(
+ "SimulatorConnectionService.onConference",
+ "connection1: "
+ + SimulatorSimCallManager.getConnectionTag(connection1)
+ + ", connection2: "
+ + SimulatorSimCallManager.getConnectionTag(connection2));
+ for (Listener listener : listeners) {
+ listener.onConference((SimulatorConnection) connection1, (SimulatorConnection) connection2);
+ }
+ }
+
private static Uri getPhoneNumber(ConnectionRequest request) {
String phoneNumber = request.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
return Uri.fromParts(PhoneAccount.SCHEME_TEL, phoneNumber, null);
@@ -116,8 +129,11 @@ public class SimulatorConnectionService extends ConnectionService {
/** Callback used to notify listeners when a new connection has been added. */
public interface Listener {
- void onNewOutgoingConnection(SimulatorConnection connection);
+ void onNewOutgoingConnection(@NonNull SimulatorConnection connection);
+
+ void onNewIncomingConnection(@NonNull SimulatorConnection connection);
- void onNewIncomingConnection(SimulatorConnection connection);
+ void onConference(
+ @NonNull SimulatorConnection connection1, @NonNull SimulatorConnection connection2);
}
}
diff --git a/java/com/android/dialer/simulator/impl/SimulatorMissedCallCreator.java b/java/com/android/dialer/simulator/impl/SimulatorMissedCallCreator.java
index f85f46602..6d4a26278 100644
--- a/java/com/android/dialer/simulator/impl/SimulatorMissedCallCreator.java
+++ b/java/com/android/dialer/simulator/impl/SimulatorMissedCallCreator.java
@@ -62,6 +62,10 @@ final class SimulatorMissedCallCreator implements SimulatorConnectionService.Lis
DISCONNECT_DELAY_MILLIS);
}
+ @Override
+ public void onConference(
+ @NonNull SimulatorConnection connection1, @NonNull SimulatorConnection connection2) {}
+
private void addNextIncomingCall(int callCount) {
if (callCount <= 0) {
LogUtil.i("SimulatorMissedCallCreator.addNextIncomingCall", "done adding calls");
diff --git a/java/com/android/dialer/simulator/impl/SimulatorSimCallManager.java b/java/com/android/dialer/simulator/impl/SimulatorSimCallManager.java
index 33eac51d1..00899fd69 100644
--- a/java/com/android/dialer/simulator/impl/SimulatorSimCallManager.java
+++ b/java/com/android/dialer/simulator/impl/SimulatorSimCallManager.java
@@ -21,6 +21,7 @@ import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
+import android.telecom.Connection;
import android.telecom.ConnectionRequest;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
@@ -47,6 +48,7 @@ public class SimulatorSimCallManager {
private static final String SIM_CALL_MANAGER_ACCOUNT_ID = "SIMULATOR_ACCOUNT_ID";
private static final String VIDEO_PROVIDER_ACCOUNT_ID = "SIMULATOR_VIDEO_ACCOUNT_ID";
private static final String EXTRA_IS_SIMULATOR_CONNECTION = "is_simulator_connection";
+ private static final String EXTRA_CONNECTION_TAG = "connection_tag";
static void register(@NonNull Context context) {
LogUtil.enterBlock("SimulatorSimCallManager.register");
@@ -85,9 +87,7 @@ public class SimulatorSimCallManager {
register(context);
extras = new Bundle(extras);
- extras.putBoolean(EXTRA_IS_SIMULATOR_CONNECTION, true);
- String connectionTag = createUniqueConnectionTag();
- extras.putBoolean(connectionTag, true);
+ extras.putAll(createSimulatorConnectionExtras());
Bundle outgoingCallExtras = new Bundle();
outgoingCallExtras.putBundle(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, extras);
@@ -102,7 +102,7 @@ public class SimulatorSimCallManager {
} catch (SecurityException e) {
throw Assert.createIllegalStateFailException("Unable to place call: " + e);
}
- return connectionTag;
+ return extras.getString(EXTRA_CONNECTION_TAG);
}
@NonNull
@@ -123,14 +123,12 @@ public class SimulatorSimCallManager {
extras = new Bundle(extras);
extras.putString(TelephonyManager.EXTRA_INCOMING_NUMBER, callerId);
- extras.putBoolean(EXTRA_IS_SIMULATOR_CONNECTION, true);
- String connectionTag = createUniqueConnectionTag();
- extras.putBoolean(connectionTag, true);
+ extras.putAll(createSimulatorConnectionExtras());
TelecomManager telecomManager = context.getSystemService(TelecomManager.class);
telecomManager.addNewIncomingCall(
isVideo ? getVideoProviderHandle(context) : getSystemPhoneAccountHandle(context), extras);
- return connectionTag;
+ return extras.getString(EXTRA_CONNECTION_TAG);
}
@NonNull
@@ -167,7 +165,7 @@ public class SimulatorSimCallManager {
}
@NonNull
- private static PhoneAccountHandle getSystemPhoneAccountHandle(@NonNull Context context) {
+ public static PhoneAccountHandle getSystemPhoneAccountHandle(@NonNull Context context) {
TelecomManager telecomManager = context.getSystemService(TelecomManager.class);
List<PhoneAccountHandle> handles;
try {
@@ -190,10 +188,37 @@ public class SimulatorSimCallManager {
}
@NonNull
+ public static String getConnectionTag(@NonNull Connection connection) {
+ String connectionTag = connection.getExtras().getString(EXTRA_CONNECTION_TAG);
+ return Assert.isNotNull(connectionTag);
+ }
+
+ @NonNull
+ public static SimulatorConnection findConnectionByTag(@NonNull String connectionTag) {
+ Assert.isNotNull(connectionTag);
+ for (Connection connection : SimulatorConnectionService.getInstance().getAllConnections()) {
+ if (connection.getExtras().getBoolean(connectionTag)) {
+ return (SimulatorConnection) connection;
+ }
+ }
+ throw Assert.createIllegalStateFailException();
+ }
+
+ @NonNull
private static String createUniqueConnectionTag() {
int callId = new Random().nextInt();
return String.format("simulator_phone_call_%x", Math.abs(callId));
}
+ @NonNull
+ static Bundle createSimulatorConnectionExtras() {
+ Bundle extras = new Bundle();
+ extras.putBoolean(EXTRA_IS_SIMULATOR_CONNECTION, true);
+ String connectionTag = createUniqueConnectionTag();
+ extras.putString(EXTRA_CONNECTION_TAG, connectionTag);
+ extras.putBoolean(connectionTag, true);
+ return extras;
+ }
+
private SimulatorSimCallManager() {}
}
diff --git a/java/com/android/dialer/simulator/impl/SimulatorSpamCallCreator.java b/java/com/android/dialer/simulator/impl/SimulatorSpamCallCreator.java
index 757658ddf..a843ec03f 100644
--- a/java/com/android/dialer/simulator/impl/SimulatorSpamCallCreator.java
+++ b/java/com/android/dialer/simulator/impl/SimulatorSpamCallCreator.java
@@ -74,6 +74,10 @@ final class SimulatorSpamCallCreator implements SimulatorConnectionService.Liste
DISCONNECT_DELAY_MILLIS);
}
+ @Override
+ public void onConference(
+ @NonNull SimulatorConnection connection1, @NonNull SimulatorConnection connection2) {}
+
private void addNextIncomingCall(int callCount) {
if (callCount <= 0) {
LogUtil.i("SimulatorSpamCallCreator.addNextIncomingCall", "done adding calls");
diff --git a/java/com/android/dialer/simulator/impl/SimulatorVideoCall.java b/java/com/android/dialer/simulator/impl/SimulatorVideoCall.java
index 3f00ab183..f7256a11c 100644
--- a/java/com/android/dialer/simulator/impl/SimulatorVideoCall.java
+++ b/java/com/android/dialer/simulator/impl/SimulatorVideoCall.java
@@ -109,6 +109,10 @@ final class SimulatorVideoCall
}
}
+ @Override
+ public void onConference(
+ @NonNull SimulatorConnection connection1, @NonNull SimulatorConnection connection2) {}
+
private boolean isVideoAccountEnabled() {
SimulatorSimCallManager.register(context);
return context
@@ -150,15 +154,12 @@ final class SimulatorVideoCall
case Event.DISCONNECT:
connection.setDisconnected(new DisconnectCause(DisconnectCause.LOCAL));
break;
- case Event.STATE_CHANGE:
- break;
- case Event.DTMF:
- break;
case Event.SESSION_MODIFY_REQUEST:
ThreadUtil.postDelayedOnUiThread(() -> connection.handleSessionModifyRequest(event), 2000);
break;
default:
- throw Assert.createIllegalStateFailException();
+ LogUtil.i("SimulatorVideoCall.onEvent", "unexpected event: " + event.type);
+ break;
}
}
}
diff --git a/java/com/android/dialer/simulator/impl/SimulatorVoiceCall.java b/java/com/android/dialer/simulator/impl/SimulatorVoiceCall.java
index 8eefb48d9..f478d55d0 100644
--- a/java/com/android/dialer/simulator/impl/SimulatorVoiceCall.java
+++ b/java/com/android/dialer/simulator/impl/SimulatorVoiceCall.java
@@ -25,6 +25,7 @@ import android.view.ActionProvider;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import com.android.dialer.common.concurrent.ThreadUtil;
+import com.android.dialer.simulator.Simulator;
import com.android.dialer.simulator.Simulator.Event;
/** Entry point in the simulator to create voice calls. */
@@ -37,7 +38,10 @@ final class SimulatorVoiceCall
return new SimulatorSubMenu(context)
.addItem("Incoming call", () -> new SimulatorVoiceCall(context).addNewIncomingCall(false))
.addItem("Outgoing call", () -> new SimulatorVoiceCall(context).addNewOutgoingCall())
- .addItem("Spam call", () -> new SimulatorVoiceCall(context).addNewIncomingCall(true));
+ .addItem("Spam call", () -> new SimulatorVoiceCall(context).addNewIncomingCall(true))
+ .addItem(
+ "GSM conference",
+ () -> new SimulatorConferenceCreator(context, Simulator.CONFERENCE_TYPE_GSM).start(5));
}
private SimulatorVoiceCall(@NonNull Context context) {
@@ -62,21 +66,28 @@ final class SimulatorVoiceCall
@Override
public void onNewOutgoingConnection(@NonNull SimulatorConnection connection) {
- if (connection.getExtras().getBoolean(connectionTag)) {
+ if (isMyConnection(connection)) {
LogUtil.i("SimulatorVoiceCall.onNewOutgoingConnection", "connection created");
handleNewConnection(connection);
- connection.setActive();
+
+ // Telecom will force the connection to switch to Dialing when we return it. Wait until after
+ // we're returned it before changing call state.
+ ThreadUtil.postOnUiThread(connection::setActive);
}
}
@Override
public void onNewIncomingConnection(@NonNull SimulatorConnection connection) {
- if (connection.getExtras().getBoolean(connectionTag)) {
+ if (isMyConnection(connection)) {
LogUtil.i("SimulatorVoiceCall.onNewIncomingConnection", "connection created");
handleNewConnection(connection);
}
}
+ @Override
+ public void onConference(
+ @NonNull SimulatorConnection connection1, @NonNull SimulatorConnection connection2) {}
+
private void handleNewConnection(@NonNull SimulatorConnection connection) {
connection.addListener(this);
connection.setConnectionCapabilities(
@@ -85,6 +96,10 @@ final class SimulatorVoiceCall
| Connection.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL);
}
+ private boolean isMyConnection(@NonNull Connection connection) {
+ return connection.getExtras().getBoolean(connectionTag);
+ }
+
@Override
public void onEvent(@NonNull SimulatorConnection connection, @NonNull Event event) {
switch (event.type) {
@@ -105,15 +120,12 @@ final class SimulatorVoiceCall
case Event.DISCONNECT:
connection.setDisconnected(new DisconnectCause(DisconnectCause.LOCAL));
break;
- case Event.STATE_CHANGE:
- break;
- case Event.DTMF:
- break;
case Event.SESSION_MODIFY_REQUEST:
ThreadUtil.postDelayedOnUiThread(() -> connection.handleSessionModifyRequest(event), 2000);
break;
default:
- throw Assert.createIllegalStateFailException();
+ LogUtil.i("SimulatorVoiceCall.onEvent", "unexpected event: " + event.type);
+ break;
}
}
}