Wiring up RTP Transport.
- Add support for loading config.xml values pertinent to
ImsPhoneCallTracker on phone initialiation.
- Add support for new shell command "d2d send -t type -v value"; this
lets us test sending D2D comms messages.
- More logging!
Test: Performed test of new adb shell command and verified that logs
indicate proper passthrough of messages.
Test: Added unit tests to verify that the D2D communicator will be set up
in a TelephonyConnection when it's an IMS connection and D2D comms is
enabled.
Bug: 163085177
Change-Id: I042e7da030e6dd41d2c20f095416185a14194213
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index ce8e9b3..5c97597 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -69,6 +69,8 @@
import com.android.internal.telephony.dataconnection.DataConnectionReasons;
import com.android.internal.telephony.dataconnection.DataConnectionReasons.DataDisallowedReasonType;
import com.android.internal.telephony.ims.ImsResolver;
+import com.android.internal.telephony.imsphone.ImsPhone;
+import com.android.internal.telephony.imsphone.ImsPhoneCallTracker;
import com.android.internal.util.IndentingPrintWriter;
import com.android.phone.settings.SettingsConstants;
import com.android.phone.vvm.CarrierVvmPackageInstalledReceiver;
@@ -360,6 +362,24 @@
defaultImsRcsPackage, PhoneFactory.getPhones().length,
new ImsFeatureBinderRepository());
mImsResolver.initialize();
+
+ // With the IMS phone created, load static config.xml values from the phone process
+ // so that it can be provided to the ImsPhoneCallTracker.
+ for (Phone p : PhoneFactory.getPhones()) {
+ Phone imsPhone = p.getImsPhone();
+ if (imsPhone != null && imsPhone instanceof ImsPhone) {
+ ImsPhone theImsPhone = (ImsPhone) imsPhone;
+ if (theImsPhone.getCallTracker() instanceof ImsPhoneCallTracker) {
+ ImsPhoneCallTracker ict = (ImsPhoneCallTracker)
+ theImsPhone.getCallTracker();
+
+ ImsPhoneCallTracker.Config config = new ImsPhoneCallTracker.Config();
+ config.isD2DCommunicationSupported = getResources().getBoolean(
+ R.bool.config_use_device_to_device_communication);
+ ict.setConfig(config);
+ }
+ }
+ }
RcsProvisioningMonitor.make(this);
}
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 3e608d2..73fbb4b 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -9759,6 +9759,32 @@
}
/**
+ * Sends a device to device communication message. Only usable via shell.
+ * @param message message to send.
+ * @param value message value.
+ */
+ @Override
+ public void sendDeviceToDeviceMessage(int message, int value) {
+ TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
+ "setCarrierSingleRegistrationEnabledOverride");
+ enforceModifyPermission();
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ TelephonyConnectionService service =
+ TelecomAccountRegistry.getInstance(null).getTelephonyConnectionService();
+ if (service == null) {
+ Rlog.e(LOG_TAG, "sendDeviceToDeviceMessage: not in a call.");
+ return;
+ }
+ service.sendTestDeviceToDeviceMessage(message, value);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+
+ /**
* Gets the config of RCS VoLTE single registration enabled for the device.
*/
@Override
diff --git a/src/com/android/phone/TelephonyShellCommand.java b/src/com/android/phone/TelephonyShellCommand.java
index ed719b6..f5bfe10 100644
--- a/src/com/android/phone/TelephonyShellCommand.java
+++ b/src/com/android/phone/TelephonyShellCommand.java
@@ -16,6 +16,11 @@
package com.android.phone;
+import static com.android.internal.telephony.d2d.Communicator.MESSAGE_CALL_AUDIO_CODEC;
+import static com.android.internal.telephony.d2d.Communicator.MESSAGE_CALL_RADIO_ACCESS_TYPE;
+import static com.android.internal.telephony.d2d.Communicator.MESSAGE_DEVICE_BATTERY_STATE;
+import static com.android.internal.telephony.d2d.Communicator.MESSAGE_DEVICE_NETWORK_COVERAGE;
+
import android.content.Context;
import android.os.Binder;
import android.os.PersistableBundle;
@@ -31,6 +36,7 @@
import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.d2d.Communicator;
import com.android.internal.telephony.emergency.EmergencyNumberTracker;
import com.android.internal.telephony.util.TelephonyUtils;
import com.android.modules.utils.BasicShellCommandHandler;
@@ -93,6 +99,9 @@
private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
+ private static final String D2D_SUBCOMMAND = "d2d";
+ private static final String D2D_SEND = "send";
+
// Take advantage of existing methods that already contain permissions checks when possible.
private final ITelephony mInterface;
@@ -175,6 +184,8 @@
return handleEndBlockSuppressionCommand();
case GBA_SUBCOMMAND:
return handleGbaCommand();
+ case D2D_SUBCOMMAND:
+ return handleD2dCommand();
case SINGLE_REGISTATION_CONFIG:
return handleSingleRegistrationConfigCommand();
default: {
@@ -210,6 +221,23 @@
onHelpCc();
onHelpGba();
onHelpSrc();
+ onHelpD2D();
+ }
+
+ private void onHelpD2D() {
+ PrintWriter pw = getOutPrintWriter();
+ pw.println("D2D Comms Commands:");
+ pw.println(" d2d send TYPE VALUE");
+ pw.println(" Sends a D2D message of specified type and value.");
+ pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
+ + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
+ pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
+ MESSAGE_CALL_AUDIO_CODEC));
+ pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
+ + Communicator.messageToString(
+ MESSAGE_DEVICE_BATTERY_STATE));
+ pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
+ + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
}
private void onHelpIms() {
@@ -540,6 +568,64 @@
return -1;
}
+ private int handleD2dCommand() {
+ String arg = getNextArg();
+ if (arg == null) {
+ onHelpD2D();
+ return 0;
+ }
+
+ switch (arg) {
+ case D2D_SEND: {
+ return handleD2dSendCommand();
+ }
+ }
+
+ return -1;
+ }
+
+ private int handleD2dSendCommand() {
+ PrintWriter errPw = getErrPrintWriter();
+ String opt;
+ int messageType = -1;
+ int messageValue = -1;
+
+
+ String arg = getNextArg();
+ if (arg == null) {
+ onHelpD2D();
+ return 0;
+ }
+ try {
+ messageType = Integer.parseInt(arg);
+ } catch (NumberFormatException e) {
+ errPw.println("message type must be a valid integer");
+ return -1;
+ }
+
+ arg = getNextArg();
+ if (arg == null) {
+ onHelpD2D();
+ return 0;
+ }
+ try {
+ messageValue = Integer.parseInt(arg);
+ } catch (NumberFormatException e) {
+ errPw.println("message value must be a valid integer");
+ return -1;
+ }
+
+ try {
+ mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
+ errPw.println("Exception: " + e.getMessage());
+ return -1;
+ }
+
+ return 0;
+ }
+
// ims set-ims-service
private int handleImsSetServiceCommand() {
PrintWriter errPw = getErrPrintWriter();
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index 6814a00..45c00e4 100755
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -3168,10 +3168,14 @@
*/
private void maybeConfigureDeviceToDeviceCommunication() {
if (!getPhone().getContext().getResources().getBoolean(
- R.bool.config_use_device_to_device_communication) || !isImsConnection()) {
+ R.bool.config_use_device_to_device_communication)) {
Log.d(this, "maybeConfigureDeviceToDeviceCommunication: not using D2D.");
return;
}
+ if (!isImsConnection()) {
+ Log.d(this, "maybeConfigureDeviceToDeviceCommunication: not an IMS connection.");
+ return;
+ }
// Implement abstracted out RTP functionality the RTP transport depends on.
RtpAdapter rtpAdapter = new RtpAdapter() {
@Override
@@ -3188,8 +3192,10 @@
public void sendRtpHeaderExtensions(
@NonNull Set<RtpHeaderExtension> rtpHeaderExtensions) {
if (!isImsConnection()) {
- Log.w(this, "sendRtpHeaderExtensions: not an ims connection.");
+ Log.w(TelephonyConnection.this, "sendRtpHeaderExtensions: not an ims conn.");
}
+ Log.d(TelephonyConnection.this, "sendRtpHeaderExtensions: sending %d messages",
+ rtpHeaderExtensions.size());
ImsPhoneConnection originalConnection =
(ImsPhoneConnection) mOriginalConnection;
originalConnection.sendRtpHeaderExtensions(rtpHeaderExtensions);
@@ -3202,6 +3208,13 @@
}
/**
+ * @return The D2D communication class, or {@code null} if not set up.
+ */
+ public @Nullable Communicator getCommunicator() {
+ return mCommunicator;
+ }
+
+ /**
* Called by {@link Communicator} associated with this {@link TelephonyConnection} when there
* are incoming device-to-device messages received.
* @param messages the incoming messages.
@@ -3210,6 +3223,14 @@
public void onMessagesReceived(@NonNull Set<Communicator.Message> messages) {
Log.i(this, "onMessagesReceived: got d2d messages: %s", messages);
// TODO: Actually do something WITH the messages.
+
+ // TODO: Remove this prior to launch.
+ // This is just here for debug purposes; send as a connection event so that it
+ // will be output in the Telecom logs.
+ for (Communicator.Message msg : messages) {
+ sendConnectionEvent("D2D_" + Communicator.messageToString(msg.getType())
+ + "_" + Communicator.valueToString(msg.getType(), msg.getValue()), null);
+ }
}
/**
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 56012c8..4b641cd 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -63,6 +63,7 @@
import com.android.internal.telephony.PhoneSwitcher;
import com.android.internal.telephony.RIL;
import com.android.internal.telephony.SubscriptionController;
+import com.android.internal.telephony.d2d.Communicator;
import com.android.internal.telephony.imsphone.ImsExternalCallTracker;
import com.android.internal.telephony.imsphone.ImsPhone;
import com.android.internal.telephony.imsphone.ImsPhoneConnection;
@@ -77,6 +78,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -2484,6 +2486,31 @@
conference.addTelephonyConferenceListener(mTelephonyConferenceListener);
}
+ /**
+ * Sends a test device to device message on the active call which supports it.
+ * Used exclusively from the telephony shell command to send a test message.
+ *
+ * @param message the message
+ * @param value the value
+ */
+ public void sendTestDeviceToDeviceMessage(int message, int value) {
+ getAllConnections().stream()
+ .filter(f -> f instanceof TelephonyConnection)
+ .forEach(t -> {
+ TelephonyConnection tc = (TelephonyConnection) t;
+ Communicator c = tc.getCommunicator();
+ if (c == null) {
+ Log.w(this, "sendTestDeviceToDeviceMessage: D2D not enabled");
+ return;
+ }
+
+ c.sendMessages(new HashSet<Communicator.Message>() {{
+ add(new Communicator.Message(message, value));
+ }});
+
+ });
+ }
+
private PhoneAccountHandle adjustAccountHandle(Phone phone,
PhoneAccountHandle origAccountHandle) {
int origSubId = PhoneUtils.getSubIdForPhoneAccountHandle(origAccountHandle);