Merge "Removed telephony apex"
diff --git a/res/layout/radio_info.xml b/res/layout/radio_info.xml
index 68c67a3..1f137b0 100644
--- a/res/layout/radio_info.xml
+++ b/res/layout/radio_info.xml
@@ -92,6 +92,12 @@
<TextView android:id="@+id/data_network" style="@style/info_value" />
</LinearLayout>
+ <!-- Override Network Type -->
+ <LinearLayout style="@style/RadioInfo_entry_layout">
+ <TextView android:text="@string/radio_info_override_network_type_label" style="@style/info_label" />
+ <TextView android:id="@+id/override_network" style="@style/info_value" />
+ </LinearLayout>
+
<!-- Voice Service Status -->
<LinearLayout style="@style/RadioInfo_entry_layout">
<TextView android:text="@string/radio_info_gsm_service_label" style="@style/info_label" />
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 1684e89..25d28de 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2130,6 +2130,8 @@
<!-- Radio Info screen. Label for a status item. Used for diagnostic info screens, precise translation isn't needed -->
<string name="radio_info_data_network_type_label">Data Network Type:</string>
<!-- Radio Info screen. Label for a status item. Used for diagnostic info screens, precise translation isn't needed -->
+ <string name="radio_info_override_network_type_label">Override Network Type:</string>
+ <!-- Radio Info screen. Label for a status item. Used for diagnostic info screens, precise translation isn't needed -->
<string name="phone_index_label">Select phone index</string>
<!-- Radio Info screen. Label for a status item. Used for diagnostic info screens, precise translation isn't needed -->
<string name="radio_info_set_perferred_label">Set Preferred Network Type:</string>
@@ -2152,17 +2154,17 @@
<!-- Radio Info screen. Label for a status item. Used for diagnostic info screens, precise translation isn't needed -->
<string name="oem_radio_info_label">OEM-specific Info/Settings</string>
<!-- Radio Info screen. Label for a status item. Used for diagnostic info screens, precise translation isn't needed -->
- <string name="radio_info_endc_available">EN-DC Available:</string>
+ <string name="radio_info_endc_available">EN-DC Available (NSA):</string>
<!-- Radio Info screen. Label for a status item. Used for diagnostic info screens, precise translation isn't needed -->
- <string name="radio_info_dcnr_restricted">DCNR Restricted:</string>
+ <string name="radio_info_dcnr_restricted">DCNR Restricted (NSA):</string>
<!-- Radio Info screen. Label for a status item. Used for diagnostic info screens, precise translation isn't needed -->
- <string name="radio_info_nr_available">NR Available:</string>
+ <string name="radio_info_nr_available">NR Available (NSA):</string>
<!-- Radio Info screen. Label for a status item. Used for diagnostic info screens, precise translation isn't needed -->
- <string name="radio_info_nr_state">NR State:</string>
+ <string name="radio_info_nr_state">NR State (NSA):</string>
<!-- Radio Info screen. Label for a status item. Used for diagnostic info screens, precise translation isn't needed -->
<string name="radio_info_nr_frequency">NR Frequency:</string>
<!-- Radio Info screen. Label for a status item. Used for diagnostic info screens, precise translation isn't needed -->
- <string name="radio_info_network_slicing_config" translatable="false">Network slicing config:</string>
+ <string name="radio_info_network_slicing_config" translatable="false">Network Slicing Config:</string>
<!-- Band Mode Selection -->
<!-- Band mode screen. Title of activity. -->
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index 036a9be..426c473 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -66,6 +66,7 @@
import com.android.internal.telephony.TelephonyCapabilities;
import com.android.internal.telephony.TelephonyComponentFactory;
import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.telephony.data.DataEvaluation.DataDisallowedReason;
import com.android.internal.telephony.dataconnection.DataConnectionReasons;
import com.android.internal.telephony.dataconnection.DataConnectionReasons.DataDisallowedReasonType;
import com.android.internal.telephony.ims.ImsResolver;
@@ -834,11 +835,26 @@
return;
}
- DataConnectionReasons reasons = new DataConnectionReasons();
- boolean dataAllowed = phone.isDataAllowed(ApnSetting.TYPE_DEFAULT, reasons);
- mDataRoamingNotifLog.log("dataAllowed=" + dataAllowed + ", reasons=" + reasons);
- if (VDBG) Log.v(LOG_TAG, "dataAllowed=" + dataAllowed + ", reasons=" + reasons);
- if (!dataAllowed && reasons.containsOnly(DataDisallowedReasonType.ROAMING_DISABLED)) {
+ boolean dataAllowed;
+ boolean notAllowedDueToRoamingOff;
+ if (phone.isUsingNewDataStack()) {
+ List<DataDisallowedReason> reasons = phone.getDataNetworkController()
+ .getInternetDataDisallowedReasons();
+ dataAllowed = reasons.isEmpty();
+ notAllowedDueToRoamingOff = (reasons.size() == 1
+ && reasons.contains(DataDisallowedReason.ROAMING_DISABLED));
+ mDataRoamingNotifLog.log("dataAllowed=" + dataAllowed + ", reasons=" + reasons);
+ if (VDBG) Log.v(LOG_TAG, "dataAllowed=" + dataAllowed + ", reasons=" + reasons);
+ } else {
+ DataConnectionReasons reasons = new DataConnectionReasons();
+ dataAllowed = phone.isDataAllowed(ApnSetting.TYPE_DEFAULT, reasons);
+ notAllowedDueToRoamingOff = reasons.containsOnly(
+ DataDisallowedReasonType.ROAMING_DISABLED);
+ mDataRoamingNotifLog.log("dataAllowed=" + dataAllowed + ", reasons=" + reasons);
+ if (VDBG) Log.v(LOG_TAG, "dataAllowed=" + dataAllowed + ", reasons=" + reasons);
+ }
+
+ if (!dataAllowed && notAllowedDueToRoamingOff) {
// No need to show it again if we never cancelled it explicitly.
if (mPrevRoamingNotification == ROAMING_NOTIFICATION_DISCONNECTED) return;
// If the only reason of no data is data roaming disabled, then we notify the user
@@ -866,7 +882,7 @@
// showed earlier.
mPrevRoamingNotification = ROAMING_NOTIFICATION_NO_NOTIFICATION;
Log.d(LOG_TAG, "Dismiss roaming notification");
- mDataRoamingNotifLog.log("Hide. data allowed=" + dataAllowed + ", reasons=" + reasons);
+ mDataRoamingNotifLog.log("Hide. data allowed=" + dataAllowed);
mHandler.sendEmptyMessage(EVENT_DATA_ROAMING_OK);
}
}
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 077c2a1..7b7be8a 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -73,6 +73,7 @@
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telephony.Annotation.ApnType;
+import android.telephony.Annotation.DataActivityType;
import android.telephony.Annotation.ThermalMitigationResult;
import android.telephony.CallForwardingInfo;
import android.telephony.CarrierConfigManager;
@@ -113,7 +114,6 @@
import android.telephony.UiccSlotMapping;
import android.telephony.UssdResponse;
import android.telephony.VisualVoicemailSmsFilterSettings;
-import android.telephony.data.ApnSetting;
import android.telephony.data.NetworkSlicingConfig;
import android.telephony.emergency.EmergencyNumber;
import android.telephony.gba.GbaAuthRequest;
@@ -154,7 +154,6 @@
import com.android.internal.telephony.CellNetworkScanResult;
import com.android.internal.telephony.CommandException;
import com.android.internal.telephony.CommandsInterface;
-import com.android.internal.telephony.DefaultPhoneNotifier;
import com.android.internal.telephony.GbaManager;
import com.android.internal.telephony.GsmCdmaPhone;
import com.android.internal.telephony.HalVersion;
@@ -2841,7 +2840,7 @@
// FIXME: subId version needed
@Override
- public boolean enableDataConnectivity() {
+ public boolean enableDataConnectivity(String callingPackage) {
enforceModifyPermission();
final long identity = Binder.clearCallingIdentity();
@@ -2851,7 +2850,7 @@
if (phone != null) {
if (phone.isUsingNewDataStack()) {
phone.getDataSettingsManager().setDataEnabled(
- TelephonyManager.DATA_ENABLED_REASON_USER, true);
+ TelephonyManager.DATA_ENABLED_REASON_USER, true, callingPackage);
} else {
phone.getDataEnabledSettings().setDataEnabled(
TelephonyManager.DATA_ENABLED_REASON_USER, true);
@@ -2867,7 +2866,7 @@
// FIXME: subId version needed
@Override
- public boolean disableDataConnectivity() {
+ public boolean disableDataConnectivity(String callingPackage) {
enforceModifyPermission();
final long identity = Binder.clearCallingIdentity();
@@ -2877,7 +2876,7 @@
if (phone != null) {
if (phone.isUsingNewDataStack()) {
phone.getDataSettingsManager().setDataEnabled(
- TelephonyManager.DATA_ENABLED_REASON_USER, false);
+ TelephonyManager.DATA_ENABLED_REASON_USER, false, callingPackage);
} else {
phone.getDataEnabledSettings().setDataEnabled(
TelephonyManager.DATA_ENABLED_REASON_USER, false);
@@ -2897,7 +2896,7 @@
try {
final Phone phone = getPhone(subId);
if (phone != null) {
- return phone.isDataAllowed(ApnSetting.TYPE_DEFAULT);
+ return phone.isDataAllowed();
} else {
return false;
}
@@ -3011,17 +3010,17 @@
}
@Override
- public int getDataActivity() {
+ public @DataActivityType int getDataActivity() {
return getDataActivityForSubId(mSubscriptionController.getDefaultDataSubId());
}
@Override
- public int getDataActivityForSubId(int subId) {
+ public @DataActivityType int getDataActivityForSubId(int subId) {
final long identity = Binder.clearCallingIdentity();
try {
final Phone phone = getPhone(subId);
if (phone != null) {
- return DefaultPhoneNotifier.convertDataActivityState(phone.getDataActivityState());
+ return phone.getDataActivityState();
} else {
return TelephonyManager.DATA_ACTIVITY_NONE;
}
@@ -5672,22 +5671,6 @@
return false;
}
- public String[] getPcscfAddress(String apnType, String callingPackage,
- String callingFeatureId) {
- final Phone defaultPhone = getDefaultPhone();
- if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mApp, defaultPhone.getSubId(),
- callingPackage, callingFeatureId, "getPcscfAddress")) {
- return new String[0];
- }
-
- final long identity = Binder.clearCallingIdentity();
- try {
- return defaultPhone.getPcscfAddress(apnType);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
/**
* Toggle IMS disable and enable for the framework to reset it. See {@link #enableIms(int)} and
* {@link #disableIms(int)}.
@@ -7630,7 +7613,7 @@
}
@Override
- public void factoryReset(int subId) {
+ public void factoryReset(int subId, String callingPackage) {
enforceSettingsPermission();
if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET)) {
return;
@@ -7646,7 +7629,7 @@
if (SubscriptionManager.isUsableSubIdValue(subId) && !mUserManager.hasUserRestriction(
UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
setDataEnabledForReason(subId, TelephonyManager.DATA_ENABLED_REASON_USER,
- getDefaultDataEnabled());
+ getDefaultDataEnabled(), callingPackage);
setNetworkSelectionModeAutomatic(subId);
Phone phone = getPhone(subId);
cleanUpAllowedNetworkTypes(phone, subId);
@@ -8362,13 +8345,14 @@
/**
* Policy control of data connection with reason {@@TelephonyManager.DataEnabledReason}
* @param subId Subscription index
- * @param reason the reason the data enable change is taking place
+ * @param reason The reason the data enable change is taking place.
* @param enabled True if enabling the data, otherwise disabling.
+ * @param callingPackage The package that changed the data enabled state.
* @hide
*/
@Override
public void setDataEnabledForReason(int subId, @TelephonyManager.DataEnabledReason int reason,
- boolean enabled) {
+ boolean enabled, String callingPackage) {
if (reason == TelephonyManager.DATA_ENABLED_REASON_USER
|| reason == TelephonyManager.DATA_ENABLED_REASON_CARRIER) {
try {
@@ -8389,7 +8373,8 @@
phone.carrierActionSetMeteredApnsEnabled(enabled);
} else {
if (phone.isUsingNewDataStack()) {
- phone.getDataSettingsManager().setDataEnabled(reason, enabled);
+ phone.getDataSettingsManager().setDataEnabled(
+ reason, enabled, callingPackage);
} else {
phone.getDataEnabledSettings().setDataEnabled(reason, enabled);
}
@@ -10111,7 +10096,7 @@
}
private int handleDataThrottlingRequest(int subId,
- DataThrottlingRequest dataThrottlingRequest) {
+ DataThrottlingRequest dataThrottlingRequest, String callingPackage) {
boolean isDataThrottlingSupported = isRadioInterfaceCapabilitySupported(
TelephonyManager.CAPABILITY_THERMAL_MITIGATION_DATA_THROTTLING);
if (!isDataThrottlingSupported && dataThrottlingRequest.getDataThrottlingAction()
@@ -10125,7 +10110,8 @@
return TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE;
}
- setDataEnabledForReason(subId, TelephonyManager.DATA_ENABLED_REASON_THERMAL, true);
+ setDataEnabledForReason(
+ subId, TelephonyManager.DATA_ENABLED_REASON_THERMAL, true, callingPackage);
if (isDataThrottlingSupported) {
int thermalMitigationResult =
@@ -10227,7 +10213,8 @@
case ThermalMitigationRequest.THERMAL_MITIGATION_ACTION_DATA_THROTTLING:
thermalMitigationResult =
handleDataThrottlingRequest(subId,
- thermalMitigationRequest.getDataThrottlingRequest());
+ thermalMitigationRequest.getDataThrottlingRequest(),
+ callingPackage);
break;
case ThermalMitigationRequest.THERMAL_MITIGATION_ACTION_VOICE_ONLY:
if (thermalMitigationRequest.getDataThrottlingRequest() != null) {
@@ -10244,7 +10231,7 @@
}
setDataEnabledForReason(subId, TelephonyManager.DATA_ENABLED_REASON_THERMAL,
- false);
+ false, callingPackage);
thermalMitigationResult = TelephonyManager.THERMAL_MITIGATION_RESULT_SUCCESS;
break;
case ThermalMitigationRequest.THERMAL_MITIGATION_ACTION_RADIO_OFF:
diff --git a/src/com/android/phone/TelephonyShellCommand.java b/src/com/android/phone/TelephonyShellCommand.java
index ac83fa9..899e391 100644
--- a/src/com/android/phone/TelephonyShellCommand.java
+++ b/src/com/android/phone/TelephonyShellCommand.java
@@ -734,7 +734,7 @@
switch (arg) {
case ENABLE: {
try {
- mInterface.enableDataConnectivity();
+ mInterface.enableDataConnectivity(mContext.getOpPackageName());
} catch (RemoteException ex) {
Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
errPw.println("Exception: " + ex.getMessage());
@@ -744,7 +744,7 @@
}
case DISABLE: {
try {
- mInterface.disableDataConnectivity();
+ mInterface.disableDataConnectivity(mContext.getOpPackageName());
} catch (RemoteException ex) {
Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
errPw.println("Exception: " + ex.getMessage());
diff --git a/src/com/android/phone/settings/RadioInfo.java b/src/com/android/phone/settings/RadioInfo.java
index 9ec128a..95788fe 100644
--- a/src/com/android/phone/settings/RadioInfo.java
+++ b/src/com/android/phone/settings/RadioInfo.java
@@ -68,6 +68,7 @@
import android.telephony.SignalStrength;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyCallback;
+import android.telephony.TelephonyDisplayInfo;
import android.telephony.TelephonyManager;
import android.telephony.data.NetworkSlicingConfig;
import android.text.TextUtils;
@@ -103,7 +104,6 @@
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@@ -237,6 +237,7 @@
private TextView mGprsState;
private TextView mVoiceNetwork;
private TextView mDataNetwork;
+ private TextView mOverrideNetwork;
private TextView mDBm;
private TextView mMwi;
private TextView mCfi;
@@ -322,7 +323,8 @@
TelephonyCallback.CallForwardingIndicatorListener,
TelephonyCallback.CellInfoListener,
TelephonyCallback.SignalStrengthsListener,
- TelephonyCallback.ServiceStateListener {
+ TelephonyCallback.ServiceStateListener,
+ TelephonyCallback.DisplayInfoListener {
@Override
public void onDataConnectionStateChanged(int state, int networkType) {
@@ -376,6 +378,10 @@
updateNrStats(serviceState);
}
+ @Override
+ public void onDisplayInfoChanged(TelephonyDisplayInfo displayInfo) {
+ updateNetworkType();
+ }
}
private void updatePhysicalChannelConfiguration(List<PhysicalChannelConfig> configs) {
@@ -488,6 +494,7 @@
mGprsState = (TextView) findViewById(R.id.gprs);
mVoiceNetwork = (TextView) findViewById(R.id.voice_network);
mDataNetwork = (TextView) findViewById(R.id.data_network);
+ mOverrideNetwork = (TextView) findViewById(R.id.override_network);
mDBm = (TextView) findViewById(R.id.dbm);
mMwi = (TextView) findViewById(R.id.mwi);
mCfi = (TextView) findViewById(R.id.cfi);
@@ -512,18 +519,7 @@
// hide 5G stats on devices that don't support 5G
if ((mTelephonyManager.getSupportedRadioAccessFamily()
& TelephonyManager.NETWORK_TYPE_BITMASK_NR) == 0) {
- ((TextView) findViewById(R.id.endc_available_label)).setVisibility(View.GONE);
- mEndcAvailable.setVisibility(View.GONE);
- ((TextView) findViewById(R.id.dcnr_restricted_label)).setVisibility(View.GONE);
- mDcnrRestricted.setVisibility(View.GONE);
- ((TextView) findViewById(R.id.nr_available_label)).setVisibility(View.GONE);
- mNrAvailable.setVisibility(View.GONE);
- ((TextView) findViewById(R.id.nr_state_label)).setVisibility(View.GONE);
- mNrState.setVisibility(View.GONE);
- ((TextView) findViewById(R.id.nr_frequency_label)).setVisibility(View.GONE);
- mNrFrequency.setVisibility(View.GONE);
- ((TextView) findViewById(R.id.network_slicing_config_label)).setVisibility(View.GONE);
- mNetworkSlicingConfig.setVisibility(View.GONE);
+ setNrStatsVisibility(View.GONE);
}
mPreferredNetworkType = (Spinner) findViewById(R.id.preferredNetworkType);
@@ -823,6 +819,7 @@
mOperatorName.setText("");
mGprsState.setText("");
mDataNetwork.setText("");
+ mOverrideNetwork.setText("");
mVoiceNetwork.setText("");
mSent.setText("");
mReceived.setText("");
@@ -845,6 +842,21 @@
mTelephonyCallback);
}
+ private void setNrStatsVisibility(int visibility) {
+ ((TextView) findViewById(R.id.endc_available_label)).setVisibility(visibility);
+ mEndcAvailable.setVisibility(visibility);
+ ((TextView) findViewById(R.id.dcnr_restricted_label)).setVisibility(visibility);
+ mDcnrRestricted.setVisibility(visibility);
+ ((TextView) findViewById(R.id.nr_available_label)).setVisibility(visibility);
+ mNrAvailable.setVisibility(visibility);
+ ((TextView) findViewById(R.id.nr_state_label)).setVisibility(visibility);
+ mNrState.setVisibility(visibility);
+ ((TextView) findViewById(R.id.nr_frequency_label)).setVisibility(visibility);
+ mNrFrequency.setVisibility(visibility);
+ ((TextView) findViewById(R.id.network_slicing_config_label)).setVisibility(visibility);
+ mNetworkSlicingConfig.setVisibility(visibility);
+ }
+
private void updateDnsCheckState() {
//FIXME: Replace with a TelephonyManager call
mDnsCheckState.setText(mPhone.isDnsCheckDisabled()
@@ -858,7 +870,6 @@
mUplinkKbps.setText(String.format("%-5d", ulbw));
}
-
private void updateSignalStrength(SignalStrength signalStrength) {
Resources r = getResources();
@@ -1146,11 +1157,14 @@
private void updateNetworkType() {
if (mPhone != null) {
- ServiceState ss = mPhone.getServiceState();
mDataNetwork.setText(ServiceState.rilRadioTechnologyToString(
mPhone.getServiceState().getRilDataRadioTechnology()));
mVoiceNetwork.setText(ServiceState.rilRadioTechnologyToString(
mPhone.getServiceState().getRilVoiceRadioTechnology()));
+ int overrideNetwork = mPhone.getDisplayInfoController().getTelephonyDisplayInfo()
+ .getOverrideNetworkType();
+ mOverrideNetwork.setText(
+ TelephonyDisplayInfo.overrideNetworkTypeToString(overrideNetwork));
}
}
@@ -1164,31 +1178,25 @@
ss = mPhone.getServiceState();
}
if (ss != null) {
- boolean isNrSa = ss.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_NR;
NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo(
NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
if (nri != null) {
DataSpecificRegistrationInfo dsri = nri.getDataSpecificInfo();
if (dsri != null) {
- mEndcAvailable.setText(isNrSa ? "N/A"
- : dsri.isEnDcAvailable ? "True" : "False");
- mDcnrRestricted.setText(isNrSa ? "N/A"
- : dsri.isDcNrRestricted ? "True" : "False");
- mNrAvailable.setText(isNrSa ? "N/A" : dsri.isNrAvailable ? "True" : "False");
+ mEndcAvailable.setText(String.valueOf(dsri.isEnDcAvailable));
+ mDcnrRestricted.setText(String.valueOf(dsri.isDcNrRestricted));
+ mNrAvailable.setText(String.valueOf(dsri.isNrAvailable));
}
}
- mNrState.setText(isNrSa ? "N/A"
- : NetworkRegistrationInfo.nrStateToString(ss.getNrState()));
- mNrFrequency.setText(isNrSa ? "N/A"
- : ServiceState.frequencyRangeToString(ss.getNrFrequencyRange()));
+ mNrState.setText(NetworkRegistrationInfo.nrStateToString(ss.getNrState()));
+ mNrFrequency.setText(ServiceState.frequencyRangeToString(ss.getNrFrequencyRange()));
}
- Executor simpleExecutor = (r) -> r.run();
CompletableFuture<NetworkSlicingConfig> resultFuture = new CompletableFuture<>();
- mTelephonyManager.getNetworkSlicingConfiguration(simpleExecutor, resultFuture::complete);
+ mTelephonyManager.getNetworkSlicingConfiguration(Runnable::run, resultFuture::complete);
try {
NetworkSlicingConfig networkSlicingConfig =
- resultFuture.get(DEFAULT_TIMEOUT_MS, MILLISECONDS);
+ resultFuture.get(DEFAULT_TIMEOUT_MS, MILLISECONDS);
mNetworkSlicingConfig.setText(networkSlicingConfig.toString());
} catch (ExecutionException | InterruptedException | TimeoutException e) {
Log.e(TAG, "Unable to get slicing config: " + e.toString());