Merge "Replace usages of hidden Telecom APIs"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 0da698e..9f90866 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -50,7 +50,7 @@
<protected-broadcast android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />
<protected-broadcast android:name="android.provider.Telephony.WAP_PUSH_RECEIVED" />
<protected-broadcast android:name="android.provider.Telephony.SMS_CB_RECEIVED" />
- <protected-broadcast android:name="android.provider.Telephony.SMS_EMERGENCY_CB_RECEIVED" />
+ <protected-broadcast android:name="android.provider.action.SMS_EMERGENCY_CB_RECEIVED" />
<protected-broadcast android:name="android.provider.Telephony.SECRET_CODE" />
<protected-broadcast android:name= "com.android.internal.stk.command" />
<protected-broadcast android:name= "com.android.internal.stk.session_end" />
@@ -457,6 +457,21 @@
</intent-filter>
</activity>
+ <!--
+ Handler for EuiccManager's public action intents. These are public and do not require
+ any special permissions to start, although the calling package name should be
+ whitelisted by the underlying eUICC service implementation (i.e. the LPA).
+ -->
+ <activity android:name=".euicc.EuiccPublicActionUiDispatcherActivity"
+ android:theme="@android:style/Theme.NoDisplay">
+ <!-- Max out priority to ensure nobody else will handle these intents. -->
+ <intent-filter android:priority="1000">
+ <action android:name=
+ "android.telephony.euicc.action.START_EUICC_ACTIVATION" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
<activity android:name="EmergencyCallbackModeExitDialog"
android:excludeFromRecents="true"
android:label="@string/ecm_exit_dialog"
diff --git a/ecc/conversion_toolset_v1/proto/Android.bp b/ecc/conversion_toolset_v1/proto/Android.bp
index f633f90..e1e0643 100644
--- a/ecc/conversion_toolset_v1/proto/Android.bp
+++ b/ecc/conversion_toolset_v1/proto/Android.bp
@@ -22,7 +22,7 @@
],
},
srcs: ["protobuf_ecc_data.proto"],
- sdk_version: "core_platform",
+ sdk_version: "system_current",
jarjar_rules: "jarjar-rules.txt",
java_version: "1.8",
-}
\ No newline at end of file
+}
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index fca8acf..8d84baf 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -15,6 +15,21 @@
-->
<resources>
+ <!-- Base attributes available to CheckBoxPreference. Copied from frameworks/base/core/res. -->
+ <declare-styleable name="CheckBoxPreference">
+ <!-- The summary for the Preference in a PreferenceActivity screen when the
+ CheckBoxPreference is checked. If separate on/off summaries are not
+ needed, the summary attribute can be used instead. -->
+ <attr name="android:summaryOn" />
+ <!-- The summary for the Preference in a PreferenceActivity screen when the
+ CheckBoxPreference is unchecked. If separate on/off summaries are not
+ needed, the summary attribute can be used instead. -->
+ <attr name="android:summaryOff" />
+ <!-- The state (true for on, or false for off) that causes dependents to be disabled. By default,
+ dependents will be disabled when this is unchecked, so the value of this preference is false. -->
+ <attr name="android:disableDependentsState" />
+ </declare-styleable>
+
<declare-styleable name="EditPhoneNumberPreference">
<!-- The enable button text. -->
<attr name="enableButtonText" format="string" />
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 1d5e7dc..fc95803 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -189,15 +189,6 @@
<item name="android:textColor">?android:attr/textColorPrimaryInverseDisableOnly</item>
</style>
- <style name="NetworkOperatorsSettingsTheme" parent="@android:style/Theme.DeviceDefault.Settings">
- <item name="android:forceDarkAllowed">true</item>
- <item name="android:switchPreferenceStyle">@style/SettingsSwitchPreference</item>
- <item name="android:preferenceCategoryStyle">@style/SettingsPreferenceCategory</item>
- <item name="android:preferenceStyle">@style/SettingsPreference</item>
- <item name="android:dialogPreferenceStyle">@style/SettingsDialogPreference</item>
- <item name="android:preferenceScreenStyle">@style/SettingsPreferenceScreen</item>
- </style>
-
<style name="TrimmedHorizontalProgressBar" parent="android:Widget.Material.ProgressBar.Horizontal">
<item name="android:indeterminateDrawable">@drawable/progress_indeterminate_horizontal_material_trimmed</item>
<item name="android:minHeight">3dip</item>
diff --git a/res/values/styles_preference.xml b/res/values/styles_preference.xml
index ceea4a6..fef4f72 100644
--- a/res/values/styles_preference.xml
+++ b/res/values/styles_preference.xml
@@ -29,10 +29,6 @@
<item name="android:singleLineTitle">false</item>
</style>
- <style name="SettingsPreferenceCategory" parent="@*android:style/Preference.DeviceDefault.Category">
- <item name="android:layout">@layout/preference_category_material_settings_with_divider</item>
- </style>
-
<style name="SettingsDialogPreference" parent="@*android:style/Preference.DeviceDefault.DialogPreference">
<item name="android:singleLineTitle">false</item>
<item name="android:iconSpaceReserved">true</item>
diff --git a/res/xml/callbarring_options.xml b/res/xml/callbarring_options.xml
index 6f2c48a..6506031 100644
--- a/res/xml/callbarring_options.xml
+++ b/res/xml/callbarring_options.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:phone="http://schemas.android.com/apk/res/com.android.phone"
+ xmlns:phone="http://schemas.android.com/apk/res-auto"
android:title="@string/call_barring_settings">
<!-- Note for all com.android.phone.EditPinPreference objects
diff --git a/res/xml/callforward_options.xml b/res/xml/callforward_options.xml
index 0ff1e90..775151e 100644
--- a/res/xml/callforward_options.xml
+++ b/res/xml/callforward_options.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:phone="http://schemas.android.com/apk/res/com.android.phone"
+ xmlns:phone="http://schemas.android.com/apk/res-auto"
android:title="@string/call_forwarding_settings">
diff --git a/res/xml/voicemail_settings.xml b/res/xml/voicemail_settings.xml
index 021a764..cbe1cf4 100644
--- a/res/xml/voicemail_settings.xml
+++ b/res/xml/voicemail_settings.xml
@@ -15,7 +15,7 @@
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:phone="http://schemas.android.com/apk/res/com.android.phone"
+ xmlns:phone="http://schemas.android.com/apk/res-auto"
android:title="@string/voicemail">
<com.android.phone.settings.VoicemailProviderListPreference
diff --git a/src/com/android/phone/CallFeaturesSetting.java b/src/com/android/phone/CallFeaturesSetting.java
index 3858595..e5e02fa 100644
--- a/src/com/android/phone/CallFeaturesSetting.java
+++ b/src/com/android/phone/CallFeaturesSetting.java
@@ -26,6 +26,7 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.os.UserManager;
@@ -181,9 +182,9 @@
startActivity(intent);
}
};
- builder.setMessage(getResources().getString(
+ builder.setMessage(getResourcesForSubId().getString(
R.string.enable_video_calling_dialog_msg))
- .setNeutralButton(getResources().getString(
+ .setNeutralButton(getResourcesForSubId().getString(
R.string.enable_video_calling_dialog_settings),
networkSettingsClickListener)
.setPositiveButton(android.R.string.ok, null)
@@ -211,9 +212,9 @@
}
mSubscriptionInfoHelper = new SubscriptionInfoHelper(this, getIntent());
- mSubscriptionInfoHelper.setActionBarTitle(
- getActionBar(), getResources(), R.string.call_settings_with_label);
mPhone = mSubscriptionInfoHelper.getPhone();
+ mSubscriptionInfoHelper.setActionBarTitle(
+ getActionBar(), getResourcesForSubId(), R.string.call_settings_with_label);
mTelecomManager = getSystemService(TelecomManager.class);
}
@@ -315,7 +316,7 @@
mButtonAutoRetry = (SwitchPreference) findPreference(BUTTON_RETRY_KEY);
mEnableVideoCalling = (SwitchPreference) findPreference(ENABLE_VIDEO_CALLING_KEY);
- mButtonWifiCalling = findPreference(getResources().getString(
+ mButtonWifiCalling = findPreference(getResourcesForSubId().getString(
R.string.wifi_calling_settings_key));
PersistableBundle carrierConfig =
@@ -424,8 +425,7 @@
} else if (!mImsMgr.isWfcEnabledByPlatform() || !mImsMgr.isWfcProvisionedOnDevice()) {
prefSet.removePreference(mButtonWifiCalling);
} else {
- String title = SubscriptionManager.getResourcesForSubId(mPhone.getContext(),
- mPhone.getSubId()).getString(R.string.wifi_calling);
+ String title = getResourcesForSubId().getString(R.string.wifi_calling);
mButtonWifiCalling.setTitle(title);
int resId = com.android.internal.R.string.wifi_calling_off_summary;
@@ -447,7 +447,7 @@
if (DBG) log("Unexpected WFC mode value: " + wfcMode);
}
}
- mButtonWifiCalling.setSummary(resId);
+ mButtonWifiCalling.setSummary(getResourcesForSubId().getString(resId));
Intent intent = mButtonWifiCalling.getIntent();
if (intent != null) {
intent.putExtra(Settings.EXTRA_SUB_ID, mPhone.getSubId());
@@ -509,9 +509,9 @@
setIntent(newIntent);
mSubscriptionInfoHelper = new SubscriptionInfoHelper(this, getIntent());
- mSubscriptionInfoHelper.setActionBarTitle(
- getActionBar(), getResources(), R.string.call_settings_with_label);
mPhone = mSubscriptionInfoHelper.getPhone();
+ mSubscriptionInfoHelper.setActionBarTitle(
+ getActionBar(), getResourcesForSubId(), R.string.call_settings_with_label);
}
private static void log(String msg) {
@@ -540,4 +540,12 @@
activity.startActivity(intent);
activity.finish();
}
+
+ private Resources getResourcesForSubId() {
+ if (mPhone != null) {
+ return SubscriptionManager.getResourcesForSubId(mPhone.getContext(), mPhone.getSubId());
+ } else {
+ return getResources();
+ }
+ }
}
diff --git a/src/com/android/phone/EditPhoneNumberPreference.java b/src/com/android/phone/EditPhoneNumberPreference.java
index 74b8a45..35af20d 100644
--- a/src/com/android/phone/EditPhoneNumberPreference.java
+++ b/src/com/android/phone/EditPhoneNumberPreference.java
@@ -136,9 +136,9 @@
a.recycle();
//get the summary settings, use CheckBoxPreference as the standard.
- a = context.obtainStyledAttributes(attrs, android.R.styleable.CheckBoxPreference, 0, 0);
- mSummaryOn = a.getString(android.R.styleable.CheckBoxPreference_summaryOn);
- mSummaryOff = a.getString(android.R.styleable.CheckBoxPreference_summaryOff);
+ a = context.obtainStyledAttributes(attrs, R.styleable.CheckBoxPreference, 0, 0);
+ mSummaryOn = a.getString(R.styleable.CheckBoxPreference_summaryOn);
+ mSummaryOff = a.getString(R.styleable.CheckBoxPreference_summaryOff);
a.recycle();
}
diff --git a/src/com/android/phone/EmergencyActionGroup.java b/src/com/android/phone/EmergencyActionGroup.java
index c090af7..53ec1eb 100644
--- a/src/com/android/phone/EmergencyActionGroup.java
+++ b/src/com/android/phone/EmergencyActionGroup.java
@@ -157,24 +157,19 @@
public void onClick(View v) {
Intent intent = (Intent) v.getTag(R.id.tag_intent);
- switch (v.getId()) {
- case R.id.action1:
- case R.id.action2:
- case R.id.action3:
- AccessibilityManager accessibilityMgr =
- (AccessibilityManager) mContext.getSystemService(
- Context.ACCESSIBILITY_SERVICE);
- if (accessibilityMgr.isTouchExplorationEnabled()) {
- getContext().startActivity(intent);
- } else {
- revealTheButton(v);
- }
- break;
- case R.id.selected_container:
- if (!mHiding) {
- getContext().startActivity(intent);
- }
- break;
+ if (v.getId() == R.id.action1 || v.getId() == R.id.action2 || v.getId() == R.id.action3) {
+ AccessibilityManager accessibilityMgr =
+ (AccessibilityManager) mContext.getSystemService(
+ Context.ACCESSIBILITY_SERVICE);
+ if (accessibilityMgr.isTouchExplorationEnabled()) {
+ getContext().startActivity(intent);
+ } else {
+ revealTheButton(v);
+ }
+ } else if (v.getId() == R.id.selected_container) {
+ if (!mHiding) {
+ getContext().startActivity(intent);
+ }
}
}
diff --git a/src/com/android/phone/EmergencyDialer.java b/src/com/android/phone/EmergencyDialer.java
index c20281a..7531aca 100644
--- a/src/com/android/phone/EmergencyDialer.java
+++ b/src/com/android/phone/EmergencyDialer.java
@@ -461,16 +461,15 @@
@Override
public boolean onKey(View view, int keyCode, KeyEvent event) {
- switch (view.getId()) {
- case R.id.digits:
- // Happen when "Done" button of the IME is pressed. This can happen when this
- // Activity is forced into landscape mode due to a desk dock.
- if (keyCode == KeyEvent.KEYCODE_ENTER
- && event.getAction() == KeyEvent.ACTION_UP) {
- placeCall();
- return true;
- }
- break;
+ if (view.getId()
+ == R.id.digits) { // Happen when "Done" button of the IME is pressed. This can
+ // happen when this
+ // Activity is forced into landscape mode due to a desk dock.
+ if (keyCode == KeyEvent.KEYCODE_ENTER
+ && event.getAction() == KeyEvent.ACTION_UP) {
+ placeCall();
+ return true;
+ }
}
return false;
}
@@ -510,27 +509,22 @@
@Override
public void onClick(View view) {
- switch (view.getId()) {
- case R.id.deleteButton: {
- keyPressed(KeyEvent.KEYCODE_DEL);
- return;
+ if (view.getId() == R.id.deleteButton) {
+ keyPressed(KeyEvent.KEYCODE_DEL);
+ return;
+ } else if (view.getId() == R.id.floating_action_button) {
+ view.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
+ placeCall();
+ return;
+ } else if (view.getId() == R.id.digits) {
+ if (mDigits.length() != 0) {
+ mDigits.setCursorVisible(true);
}
- case R.id.floating_action_button: {
- view.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
- placeCall();
- return;
- }
- case R.id.digits: {
- if (mDigits.length() != 0) {
- mDigits.setCursorVisible(true);
- }
- return;
- }
- case R.id.floating_action_button_dialpad: {
- mDigits.getText().clear();
- switchView(mDialpadView, mEmergencyShortcutView, true);
- return;
- }
+ return;
+ } else if (view.getId() == R.id.floating_action_button_dialpad) {
+ mDigits.getText().clear();
+ switchView(mDialpadView, mEmergencyShortcutView, true);
+ return;
}
}
@@ -539,67 +533,54 @@
if (!pressed) {
return;
}
- switch (view.getId()) {
- case R.id.one: {
- playTone(ToneGenerator.TONE_DTMF_1);
- keyPressed(KeyEvent.KEYCODE_1);
- return;
- }
- case R.id.two: {
- playTone(ToneGenerator.TONE_DTMF_2);
- keyPressed(KeyEvent.KEYCODE_2);
- return;
- }
- case R.id.three: {
- playTone(ToneGenerator.TONE_DTMF_3);
- keyPressed(KeyEvent.KEYCODE_3);
- return;
- }
- case R.id.four: {
- playTone(ToneGenerator.TONE_DTMF_4);
- keyPressed(KeyEvent.KEYCODE_4);
- return;
- }
- case R.id.five: {
- playTone(ToneGenerator.TONE_DTMF_5);
- keyPressed(KeyEvent.KEYCODE_5);
- return;
- }
- case R.id.six: {
- playTone(ToneGenerator.TONE_DTMF_6);
- keyPressed(KeyEvent.KEYCODE_6);
- return;
- }
- case R.id.seven: {
- playTone(ToneGenerator.TONE_DTMF_7);
- keyPressed(KeyEvent.KEYCODE_7);
- return;
- }
- case R.id.eight: {
- playTone(ToneGenerator.TONE_DTMF_8);
- keyPressed(KeyEvent.KEYCODE_8);
- return;
- }
- case R.id.nine: {
- playTone(ToneGenerator.TONE_DTMF_9);
- keyPressed(KeyEvent.KEYCODE_9);
- return;
- }
- case R.id.zero: {
- playTone(ToneGenerator.TONE_DTMF_0);
- keyPressed(KeyEvent.KEYCODE_0);
- return;
- }
- case R.id.pound: {
- playTone(ToneGenerator.TONE_DTMF_P);
- keyPressed(KeyEvent.KEYCODE_POUND);
- return;
- }
- case R.id.star: {
- playTone(ToneGenerator.TONE_DTMF_S);
- keyPressed(KeyEvent.KEYCODE_STAR);
- return;
- }
+ if (view.getId() == R.id.one) {
+ playTone(ToneGenerator.TONE_DTMF_1);
+ keyPressed(KeyEvent.KEYCODE_1);
+ return;
+ } else if (view.getId() == R.id.two) {
+ playTone(ToneGenerator.TONE_DTMF_2);
+ keyPressed(KeyEvent.KEYCODE_2);
+ return;
+ } else if (view.getId() == R.id.three) {
+ playTone(ToneGenerator.TONE_DTMF_3);
+ keyPressed(KeyEvent.KEYCODE_3);
+ return;
+ } else if (view.getId() == R.id.four) {
+ playTone(ToneGenerator.TONE_DTMF_4);
+ keyPressed(KeyEvent.KEYCODE_4);
+ return;
+ } else if (view.getId() == R.id.five) {
+ playTone(ToneGenerator.TONE_DTMF_5);
+ keyPressed(KeyEvent.KEYCODE_5);
+ return;
+ } else if (view.getId() == R.id.six) {
+ playTone(ToneGenerator.TONE_DTMF_6);
+ keyPressed(KeyEvent.KEYCODE_6);
+ return;
+ } else if (view.getId() == R.id.seven) {
+ playTone(ToneGenerator.TONE_DTMF_7);
+ keyPressed(KeyEvent.KEYCODE_7);
+ return;
+ } else if (view.getId() == R.id.eight) {
+ playTone(ToneGenerator.TONE_DTMF_8);
+ keyPressed(KeyEvent.KEYCODE_8);
+ return;
+ } else if (view.getId() == R.id.nine) {
+ playTone(ToneGenerator.TONE_DTMF_9);
+ keyPressed(KeyEvent.KEYCODE_9);
+ return;
+ } else if (view.getId() == R.id.zero) {
+ playTone(ToneGenerator.TONE_DTMF_0);
+ keyPressed(KeyEvent.KEYCODE_0);
+ return;
+ } else if (view.getId() == R.id.pound) {
+ playTone(ToneGenerator.TONE_DTMF_P);
+ keyPressed(KeyEvent.KEYCODE_POUND);
+ return;
+ } else if (view.getId() == R.id.star) {
+ playTone(ToneGenerator.TONE_DTMF_S);
+ keyPressed(KeyEvent.KEYCODE_STAR);
+ return;
}
}
@@ -609,16 +590,13 @@
@Override
public boolean onLongClick(View view) {
int id = view.getId();
- switch (id) {
- case R.id.deleteButton: {
- mDigits.getText().clear();
- return true;
- }
- case R.id.zero: {
- removePreviousDigitIfPossible();
- keyPressed(KeyEvent.KEYCODE_PLUS);
- return true;
- }
+ if (id == R.id.deleteButton) {
+ mDigits.getText().clear();
+ return true;
+ } else if (id == R.id.zero) {
+ removePreviousDigitIfPossible();
+ keyPressed(KeyEvent.KEYCODE_PLUS);
+ return true;
}
return false;
}
diff --git a/src/com/android/phone/EmergencyInfoGroup.java b/src/com/android/phone/EmergencyInfoGroup.java
index 186de03..f5aca7f 100644
--- a/src/com/android/phone/EmergencyInfoGroup.java
+++ b/src/com/android/phone/EmergencyInfoGroup.java
@@ -207,26 +207,21 @@
@Override
public void onClick(View view) {
- switch (view.getId()) {
- case R.id.emergency_info_view:
- AccessibilityManager accessibilityMgr =
- (AccessibilityManager) mContext.getSystemService(
- Context.ACCESSIBILITY_SERVICE);
- if (accessibilityMgr.isTouchExplorationEnabled()) {
- if (mOnConfirmClickListener != null) {
- mOnConfirmClickListener.onConfirmClick(this);
- }
- } else {
- revealSelectedButton();
- }
- break;
- case R.id.emergency_info_confirm_view:
+ if (view.getId() == R.id.emergency_info_view) {
+ AccessibilityManager accessibilityMgr =
+ (AccessibilityManager) mContext.getSystemService(
+ Context.ACCESSIBILITY_SERVICE);
+ if (accessibilityMgr.isTouchExplorationEnabled()) {
if (mOnConfirmClickListener != null) {
mOnConfirmClickListener.onConfirmClick(this);
}
- break;
- default:
- break;
+ } else {
+ revealSelectedButton();
+ }
+ } else if (view.getId() == R.id.emergency_info_confirm_view) {
+ if (mOnConfirmClickListener != null) {
+ mOnConfirmClickListener.onConfirmClick(this);
+ }
}
}
diff --git a/src/com/android/phone/EmergencyShortcutButton.java b/src/com/android/phone/EmergencyShortcutButton.java
index 9e51e82..d147ce4 100644
--- a/src/com/android/phone/EmergencyShortcutButton.java
+++ b/src/com/android/phone/EmergencyShortcutButton.java
@@ -182,26 +182,23 @@
@Override
public void onClick(View view) {
- switch (view.getId()) {
- case R.id.emergency_call_number_info_view:
- AccessibilityManager accessibilityMgr =
- (AccessibilityManager) mContext.getSystemService(
- Context.ACCESSIBILITY_SERVICE);
- if (accessibilityMgr.isTouchExplorationEnabled()) {
- // TalkBack itself includes a prompt to confirm click action implicitly,
- // so we don't need an additional confirmation with second tap on button.
- if (mOnConfirmClickListener != null) {
- mOnConfirmClickListener.onConfirmClick(this);
- }
- } else {
- revealSelectedButton();
- }
- break;
- case R.id.emergency_call_confirm_view:
+ if (view.getId() == R.id.emergency_call_number_info_view) {
+ AccessibilityManager accessibilityMgr =
+ (AccessibilityManager) mContext.getSystemService(
+ Context.ACCESSIBILITY_SERVICE);
+ if (accessibilityMgr.isTouchExplorationEnabled()) {
+ // TalkBack itself includes a prompt to confirm click action implicitly,
+ // so we don't need an additional confirmation with second tap on button.
if (mOnConfirmClickListener != null) {
mOnConfirmClickListener.onConfirmClick(this);
}
- break;
+ } else {
+ revealSelectedButton();
+ }
+ } else if (view.getId() == R.id.emergency_call_confirm_view) {
+ if (mOnConfirmClickListener != null) {
+ mOnConfirmClickListener.onConfirmClick(this);
+ }
}
}
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index b9c6728..1eb5f50 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -369,6 +369,10 @@
// register for MMI/USSD
mCM.registerForMmiComplete(mHandler, MMI_COMPLETE, null);
+ // Initialize cell status using current airplane mode.
+ handleAirplaneModeChange(this, Settings.Global.getInt(getContentResolver(),
+ Settings.Global.AIRPLANE_MODE_ON, AIRPLANE_OFF));
+
// Register for misc other intent broadcasts.
IntentFilter intentFilter =
new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 95a0daa..80f8e08 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -57,6 +57,7 @@
import android.os.UserManager;
import android.os.WorkSource;
import android.preference.PreferenceManager;
+import android.provider.DeviceConfig;
import android.provider.Settings;
import android.provider.Telephony;
import android.telecom.PhoneAccount;
@@ -262,6 +263,8 @@
private static final int EVENT_GET_MODEM_STATUS_DONE = 71;
private static final int CMD_SET_FORBIDDEN_PLMNS = 72;
private static final int EVENT_SET_FORBIDDEN_PLMNS_DONE = 73;
+ private static final int CMD_ERASE_MODEM_CONFIG = 74;
+ private static final int EVENT_ERASE_MODEM_CONFIG_DONE = 75;
// Parameters of select command.
private static final int SELECT_COMMAND = 0xA4;
@@ -302,6 +305,12 @@
private static final int MANUFACTURER_CODE_LENGTH = 8;
/**
+ * Experiment flag to enable erase modem config on reset network, default value is false
+ */
+ public static final String RESET_NETWORK_ERASE_MODEM_CONFIG_ENABLED =
+ "reset_network_erase_modem_config_enabled";
+
+ /**
* A request object to use for transmitting data to an ICC.
*/
private static final class IccAPDUArgument {
@@ -1214,6 +1223,13 @@
((SIMRecords) uiccApp.getIccRecords())
.setForbiddenPlmns(onCompleted, fplmns);
}
+ case CMD_ERASE_MODEM_CONFIG:
+ request = (MainThreadRequest) msg.obj;
+ onCompleted = obtainMessage(EVENT_ERASE_MODEM_CONFIG_DONE, request);
+ defaultPhone.eraseModemConfig(onCompleted);
+ break;
+ case EVENT_ERASE_MODEM_CONFIG_DONE:
+ handleNullReturnEvent(msg, "eraseModemConfig");
break;
default:
Log.w(LOG_TAG, "MainThreadHandler: unexpected message code: " + msg.what);
@@ -1423,6 +1439,20 @@
return PhoneFactory.getPhone(mSubscriptionController.getPhoneId(subId));
}
+ private void sendEraseModemConfig(Phone phone) {
+ if (phone != null) {
+ TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+ mApp, phone.getSubId(), "eraseModemConfig");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ Boolean success = (Boolean) sendRequest(CMD_ERASE_MODEM_CONFIG, null);
+ if (DBG) log("eraseModemConfig:" + ' ' + (success ? "ok" : "fail"));
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ }
+
public void dial(String number) {
dialForSubscriber(getPreferredVoiceSubscription(), number);
}
@@ -2398,6 +2428,11 @@
mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
}
+ private void enforceActiveEmergencySessionPermission() {
+ mApp.enforceCallingOrSelfPermission(
+ android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION, null);
+ }
+
/**
* Make sure the caller has the CALL_PHONE permission.
*
@@ -4900,7 +4935,7 @@
* @hide
*/
@Override
- public boolean isTetherApnRequiredForSubscriber(int subId) {
+ public boolean isTetheringApnRequiredForSubscriber(int subId) {
enforceModifyPermission();
final long identity = Binder.clearCallingIdentity();
final Phone phone = getPhone(subId);
@@ -5033,6 +5068,52 @@
}
}
+ private int getCarrierPrivilegeStatusFromCarrierConfigRules(int privilegeFromSim,
+ Phone phone) {
+ //load access rules from carrier configs, and check those as well: b/139133814
+ SubscriptionController subController = SubscriptionController.getInstance();
+ if (privilegeFromSim == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS
+ || subController == null) return privilegeFromSim;
+
+ int uid = Binder.getCallingUid();
+ PackageManager pkgMgr = phone.getContext().getPackageManager();
+ String[] packages = pkgMgr.getPackagesForUid(uid);
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ SubscriptionInfo subInfo = subController.getSubscriptionInfo(phone.getSubId());
+ SubscriptionManager subManager = (SubscriptionManager)
+ phone.getContext().getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+ for (String pkg : packages) {
+ if (subManager.canManageSubscription(subInfo, pkg)) {
+ return TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
+ }
+ }
+ return privilegeFromSim;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ private int getCarrierPrivilegeStatusFromCarrierConfigRules(int privilegeFromSim, Phone phone,
+ String pkgName) {
+ //load access rules from carrier configs, and check those as well: b/139133814
+ SubscriptionController subController = SubscriptionController.getInstance();
+ if (privilegeFromSim == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS
+ || subController == null) return privilegeFromSim;
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ SubscriptionInfo subInfo = subController.getSubscriptionInfo(phone.getSubId());
+ SubscriptionManager subManager = (SubscriptionManager)
+ phone.getContext().getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+ return subManager.canManageSubscription(subInfo, pkgName)
+ ? TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS : privilegeFromSim;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
@Override
public int getCarrierPrivilegeStatus(int subId) {
final Phone phone = getPhone(subId);
@@ -5045,8 +5126,10 @@
loge("getCarrierPrivilegeStatus: No UICC");
return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
}
- return card.getCarrierPrivilegeStatusForCurrentTransaction(
- phone.getContext().getPackageManager());
+
+ return getCarrierPrivilegeStatusFromCarrierConfigRules(
+ card.getCarrierPrivilegeStatusForCurrentTransaction(
+ phone.getContext().getPackageManager()), phone);
}
@Override
@@ -5062,7 +5145,9 @@
loge("getCarrierPrivilegeStatusForUid: No UICC");
return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
}
- return profile.getCarrierPrivilegeStatusForUid(phone.getContext().getPackageManager(), uid);
+ return getCarrierPrivilegeStatusFromCarrierConfigRules(
+ profile.getCarrierPrivilegeStatusForUid(
+ phone.getContext().getPackageManager(), uid), phone);
}
@Override
@@ -5077,8 +5162,9 @@
loge("checkCarrierPrivilegesForPackage: No UICC on subId " + subId);
return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
}
-
- return card.getCarrierPrivilegeStatus(mApp.getPackageManager(), pkgName);
+ return getCarrierPrivilegeStatusFromCarrierConfigRules(
+ card.getCarrierPrivilegeStatus(mApp.getPackageManager(), pkgName),
+ getPhone(phoneId), pkgName);
}
@Override
@@ -5093,7 +5179,9 @@
continue;
}
- result = card.getCarrierPrivilegeStatus(mApp.getPackageManager(), pkgName);
+ result = getCarrierPrivilegeStatusFromCarrierConfigRules(
+ card.getCarrierPrivilegeStatus(mApp.getPackageManager(), pkgName),
+ getPhone(i), pkgName);
if (result == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
break;
}
@@ -5128,9 +5216,9 @@
if (packages == null) {
// Only check packages in user 0 for now
packages = pm.getInstalledPackagesAsUser(
- PackageManager.MATCH_DISABLED_COMPONENTS
- | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
- | PackageManager.GET_SIGNATURES, UserHandle.USER_SYSTEM);
+ PackageManager.MATCH_DISABLED_COMPONENTS
+ | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ | PackageManager.GET_SIGNATURES, UserHandle.USER_SYSTEM);
}
for (int p = packages.size() - 1; p >= 0; p--) {
PackageInfo pkgInfo = packages.get(p);
@@ -5783,6 +5871,13 @@
if (slotId > SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
ImsManager.getInstance(mApp, slotId).factoryReset();
}
+
+ // Erase modem config if erase modem on network setting is enabled.
+ String configValue = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_TELEPHONY,
+ RESET_NETWORK_ERASE_MODEM_CONFIG_ENABLED);
+ if (configValue != null && Boolean.parseBoolean(configValue)) {
+ sendEraseModemConfig(getDefaultPhone());
+ }
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -7101,6 +7196,57 @@
}
@Override
+ public int getEmergencyNumberDbVersion(int subId) {
+ enforceReadPrivilegedPermission("getEmergencyNumberDbVersion");
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ final Phone phone = getPhone(subId);
+ if (phone == null) {
+ loge("getEmergencyNumberDbVersion fails with invalid subId: " + subId);
+ return TelephonyManager.INVALID_EMERGENCY_NUMBER_DB_VERSION;
+ }
+ return phone.getEmergencyNumberDbVersion();
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void notifyOtaEmergencyNumberDbInstalled() {
+ enforceModifyPermission();
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ for (Phone phone: PhoneFactory.getPhones()) {
+ EmergencyNumberTracker tracker = phone.getEmergencyNumberTracker();
+ if (tracker != null) {
+ tracker.updateOtaEmergencyNumberDatabase();
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void updateTestOtaEmergencyNumberDbFilePath(String otaFilePath) {
+ enforceActiveEmergencySessionPermission();
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ for (Phone phone: PhoneFactory.getPhones()) {
+ EmergencyNumberTracker tracker = phone.getEmergencyNumberTracker();
+ if (tracker != null) {
+ tracker.updateTestOtaEmergencyNumberDbFilePath(otaFilePath);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
public List<String> getCertsFromCarrierPrivilegeAccessRules(int subId) {
enforceReadPrivilegedPermission("getCertsFromCarrierPrivilegeAccessRules");
Phone phone = getPhone(subId);
diff --git a/src/com/android/phone/TelephonyShellCommand.java b/src/com/android/phone/TelephonyShellCommand.java
index 428c006..ebadf88 100644
--- a/src/com/android/phone/TelephonyShellCommand.java
+++ b/src/com/android/phone/TelephonyShellCommand.java
@@ -18,7 +18,6 @@
import android.content.Context;
import android.os.Binder;
-import android.os.Build;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.RemoteException;
@@ -31,6 +30,7 @@
import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.emergency.EmergencyNumberTracker;
+import com.android.internal.telephony.util.TelephonyUtils;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -623,7 +623,7 @@
private int handleCcCommand() {
// Verify that the user is allowed to run the command. Only allowed in rooted device in a
// non user build.
- if (Binder.getCallingUid() != Process.ROOT_UID || Build.IS_USER) {
+ if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
getErrPrintWriter().println("cc: Permission denied.");
return -1;
}
diff --git a/src/com/android/phone/euicc/EuiccPublicActionUiDispatcherActivity.java b/src/com/android/phone/euicc/EuiccPublicActionUiDispatcherActivity.java
new file mode 100644
index 0000000..64a40b9
--- /dev/null
+++ b/src/com/android/phone/euicc/EuiccPublicActionUiDispatcherActivity.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2019 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.phone.euicc;
+
+import android.annotation.Nullable;
+import android.content.Intent;
+import android.service.euicc.EuiccService;
+import android.telephony.euicc.EuiccManager;
+import android.util.Log;
+
+/**
+ * Trampoline activity to forward public eUICC intents to the active UI implementation.
+ *
+ * <p>Unlike {@link EuiccUiDispatcherActivity}, this activity does not require any permissions to
+ * start.
+ */
+public class EuiccPublicActionUiDispatcherActivity extends EuiccUiDispatcherActivity {
+ private static final String TAG = "EuiccPublicActionUiDispatcherActivity";
+
+ @Override
+ @Nullable
+ protected Intent getEuiccUiIntent() {
+ String action = getIntent().getAction();
+
+ Intent intent = new Intent();
+ // Propagate the extras from the original Intent.
+ intent.putExtras(getIntent());
+ switch (action) {
+ case EuiccManager.ACTION_START_EUICC_ACTIVATION:
+ intent.setAction(EuiccService.ACTION_START_EUICC_ACTIVATION);
+ break;
+ default:
+ Log.w(TAG, "Unsupported action: " + action);
+ return null;
+ }
+
+ return intent;
+ }
+}
diff --git a/src/com/android/phone/euicc/EuiccUiDispatcherActivity.java b/src/com/android/phone/euicc/EuiccUiDispatcherActivity.java
index 4c85818..96f04e1 100644
--- a/src/com/android/phone/euicc/EuiccUiDispatcherActivity.java
+++ b/src/com/android/phone/euicc/EuiccUiDispatcherActivity.java
@@ -27,6 +27,7 @@
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.UserHandle;
import android.service.euicc.EuiccService;
import android.telephony.euicc.EuiccManager;
import android.util.Log;
@@ -138,7 +139,7 @@
protected void grantDefaultPermissionsToActiveLuiApp(ActivityInfo activityInfo) {
try {
mPackageManager.grantDefaultPermissionsToActiveLuiApp(
- activityInfo.packageName, getUserId());
+ activityInfo.packageName, UserHandle.myUserId());
} catch (RemoteException e) {
Log.e(TAG, "Failed to grant permissions to active LUI app.", e);
}
@@ -150,7 +151,8 @@
try {
Set<String> luiApps = getAllLuiAppPackageNames(intent);
String[] luiAppsArray = luiApps.toArray(new String[luiApps.size()]);
- mPackageManager.revokeDefaultPermissionsFromLuiApps(luiAppsArray, getUserId());
+ mPackageManager.revokeDefaultPermissionsFromLuiApps(luiAppsArray,
+ UserHandle.myUserId());
} catch (RemoteException e) {
Log.e(TAG, "Failed to revoke LUI app permissions.");
throw new RuntimeException(e);
diff --git a/src/com/android/services/telephony/DisconnectCauseUtil.java b/src/com/android/services/telephony/DisconnectCauseUtil.java
index 4a5fb4a..9e32f00 100644
--- a/src/com/android/services/telephony/DisconnectCauseUtil.java
+++ b/src/com/android/services/telephony/DisconnectCauseUtil.java
@@ -117,6 +117,8 @@
private static int toTelecomDisconnectCauseCode(int telephonyDisconnectCause) {
switch (telephonyDisconnectCause) {
case android.telephony.DisconnectCause.LOCAL:
+ // The call was still disconnected locally, so this is not an error condition.
+ case android.telephony.DisconnectCause.OUTGOING_EMERGENCY_CALL_PLACED:
return DisconnectCause.LOCAL;
case android.telephony.DisconnectCause.NORMAL:
@@ -797,6 +799,8 @@
break;
case android.telephony.DisconnectCause.IMS_ACCESS_BLOCKED:
return DisconnectCause.REASON_IMS_ACCESS_BLOCKED;
+ case android.telephony.DisconnectCause.OUTGOING_EMERGENCY_CALL_PLACED:
+ return DisconnectCause.REASON_EMERGENCY_CALL_PLACED;
}
// If no specific code-mapping found, then fall back to using the reason.
diff --git a/src/com/android/services/telephony/TelecomAccountRegistry.java b/src/com/android/services/telephony/TelecomAccountRegistry.java
index 8bf9d42..092e08b 100644
--- a/src/com/android/services/telephony/TelecomAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecomAccountRegistry.java
@@ -288,7 +288,7 @@
mIsRttCapable = false;
}
- mIsVideoCapable = mPhone.isVideoEnabled() && !mIsRttCapable;
+ mIsVideoCapable = mPhone.isVideoEnabled();
boolean isVideoEnabledByPlatform = ImsManager.getInstance(mPhone.getContext(),
mPhone.getPhoneId()).isVtEnabledByPlatform();
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index 94a2cd5..702e6f7 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
+import android.content.res.Resources;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.AsyncResult;
@@ -36,11 +37,13 @@
import android.telecom.StatusHints;
import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
+import android.telephony.Annotation.RilRadioTechnology;
import android.telephony.CarrierConfigManager;
import android.telephony.DisconnectCause;
import android.telephony.PhoneNumberUtils;
import android.telephony.Rlog;
import android.telephony.ServiceState;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.ims.ImsCallProfile;
import android.text.TextUtils;
@@ -136,7 +139,7 @@
if (connection != null &&
((connection.getAddress() != null &&
mOriginalConnection.getAddress() != null &&
- mOriginalConnection.getAddress().contains(connection.getAddress())) ||
+ mOriginalConnection.getAddress().equals(connection.getAddress())) ||
connection.getState() == mOriginalConnection.getStateBeforeHandover())) {
Log.d(TelephonyConnection.this,
"SettingOriginalConnection " + mOriginalConnection.toString()
@@ -404,7 +407,9 @@
}
}
if (messageId != -1 && getPhone() != null && getPhone().getContext() != null) {
- return getPhone().getContext().getText(messageId);
+ Resources res = SubscriptionManager.getResourcesForSubId(
+ getPhone().getContext(), getPhone().getSubId());
+ return res.getText(messageId);
} else {
return null;
}
@@ -502,7 +507,7 @@
* @param vrat the RIL Voice Radio Technology used for current connection.
*/
@Override
- public void onCallRadioTechChanged(@ServiceState.RilRadioTechnology int vrat) {
+ public void onCallRadioTechChanged(@RilRadioTechnology int vrat) {
mHandler.obtainMessage(MSG_SET_CALL_RADIO_TECH, vrat).sendToTarget();
}
@@ -645,6 +650,7 @@
@Override
public void onRttTerminated() {
updateConnectionProperties();
+ refreshConferenceSupported();
sendRttSessionRemotelyTerminated();
}
@@ -762,6 +768,11 @@
private boolean mShowPreciseFailedCause;
/**
+ * Provides a DisconnectCause associated with a hang up request.
+ */
+ private int mHangupDisconnectCause = DisconnectCause.NOT_VALID;
+
+ /**
* Listeners to our TelephonyConnection specific callbacks
*/
private final Set<TelephonyConnectionListener> mTelephonyListeners = Collections.newSetFromMap(
@@ -1480,6 +1491,7 @@
protected void hangup(int telephonyDisconnectCode) {
if (mOriginalConnection != null) {
+ mHangupDisconnectCause = telephonyDisconnectCode;
try {
// Hanging up a ringing call requires that we invoke call.hangup() as opposed to
// connection.hangup(). Without this change, the party originating the call
@@ -1732,9 +1744,16 @@
preciseDisconnectCause =
mOriginalConnection.getPreciseDisconnectCause();
}
+ int disconnectCause = mOriginalConnection.getDisconnectCause();
+ if ((mHangupDisconnectCause != DisconnectCause.NOT_VALID)
+ && (mHangupDisconnectCause != disconnectCause)) {
+ Log.i(LOG_TAG, "setDisconnected: override cause: " + disconnectCause
+ + " -> " + mHangupDisconnectCause);
+ disconnectCause = mHangupDisconnectCause;
+ }
setTelephonyConnectionDisconnected(
DisconnectCauseUtil.toTelecomDisconnectCause(
- mOriginalConnection.getDisconnectCause(),
+ disconnectCause,
preciseDisconnectCause,
mOriginalConnection.getVendorDisconnectCause(),
getPhone().getPhoneId()));
@@ -2189,8 +2208,10 @@
: R.string.status_hint_label_wifi_call;
Context context = getPhone().getContext();
+ Resources res =
+ SubscriptionManager.getResourcesForSubId(context, getPhone().getSubId());
setTelephonyStatusHints(new StatusHints(
- context.getString(labelId),
+ res.getString(labelId),
Icon.createWithResource(
context, R.drawable.ic_signal_wifi_4_bar_24dp),
null /* extras */));
@@ -2570,7 +2591,7 @@
* @param vrat the RIL Voice Radio Technology used for current connection,
* see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
*/
- public final void setCallRadioTech(@ServiceState.RilRadioTechnology int vrat) {
+ public final void setCallRadioTech(@RilRadioTechnology int vrat) {
Bundle extras = getExtras();
if (extras == null) {
extras = new Bundle();
@@ -2599,7 +2620,7 @@
* @return the RIL voice radio technology used for current connection,
* see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
*/
- public final @ServiceState.RilRadioTechnology int getCallRadioTech() {
+ public final @RilRadioTechnology int getCallRadioTech() {
int voiceNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
Bundle extras = getExtras();
if (extras != null) {
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index c2c4c50..cfe614a 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -182,6 +182,8 @@
public boolean isLocked = false;
// Is the emergency number associated with the slot
public boolean hasDialedEmergencyNumber = false;
+ //SimState
+ public int simState;
public SlotStatus(int slotId, int capabilities) {
this.slotId = slotId;
@@ -814,7 +816,7 @@
final TelephonyConnection connection =
createConnectionFor(phone, null, true /* isOutgoing */, request.getAccountHandle(),
- request.getTelecomCallId(), request.getAddress(), request.getVideoState());
+ request.getTelecomCallId());
if (connection == null) {
return Connection.createFailedConnection(
DisconnectCauseUtil.toTelecomDisconnectCause(
@@ -873,15 +875,9 @@
return Connection.createCanceledConnection();
}
- // We should rely on the originalConnection to get the video state. The request coming
- // from Telecom does not know the video state of the incoming call.
- int videoState = originalConnection != null ? originalConnection.getVideoState() :
- VideoProfile.STATE_AUDIO_ONLY;
-
TelephonyConnection connection =
createConnectionFor(phone, originalConnection, false /* isOutgoing */,
- request.getAccountHandle(), request.getTelecomCallId(),
- request.getAddress(), videoState);
+ request.getAccountHandle(), request.getTelecomCallId());
handleIncomingRtt(request, originalConnection);
if (connection == null) {
return Connection.createCanceledConnection();
@@ -938,6 +934,61 @@
}
@Override
+ public void onCreateIncomingConnectionFailed(PhoneAccountHandle connectionManagerPhoneAccount,
+ ConnectionRequest request) {
+ Log.i(this, "onCreateIncomingConnectionFailed, request: " + request);
+ // If there is an incoming emergency CDMA Call (while the phone is in ECBM w/ No SIM),
+ // make sure the PhoneAccount lookup retrieves the default Emergency Phone.
+ PhoneAccountHandle accountHandle = request.getAccountHandle();
+ boolean isEmergency = false;
+ if (accountHandle != null && PhoneUtils.EMERGENCY_ACCOUNT_HANDLE_ID.equals(
+ accountHandle.getId())) {
+ Log.w(this, "onCreateIncomingConnectionFailed:Emergency call failed... ");
+ isEmergency = true;
+ }
+ Phone phone = getPhoneForAccount(accountHandle, isEmergency,
+ /* Note: when not an emergency, handle can be null for unknown callers */
+ request.getAddress() == null ? null : request.getAddress().getSchemeSpecificPart());
+ if (phone == null) {
+ Log.w(this, "onCreateIncomingConnectionFailed: can not find corresponding phone.");
+ return;
+ }
+
+ Call call = phone.getRingingCall();
+ if (!call.getState().isRinging()) {
+ Log.w(this, "onCreateIncomingConnectionFailed, no ringing call found for failed call");
+ return;
+ }
+
+ com.android.internal.telephony.Connection originalConnection =
+ call.getState() == Call.State.WAITING
+ ? call.getLatestConnection() : call.getEarliestConnection();
+ TelephonyConnection knownConnection =
+ getConnectionForOriginalConnection(originalConnection);
+ if (knownConnection != null) {
+ Log.w(this, "onCreateIncomingConnectionFailed, original connection already registered."
+ + " Hanging it up.");
+ knownConnection.onAbort();
+ return;
+ }
+
+ TelephonyConnection connection =
+ createConnectionFor(phone, originalConnection, false /* isOutgoing */,
+ request.getAccountHandle(), request.getTelecomCallId());
+ if (connection == null) {
+ Log.w(this, "onCreateIncomingConnectionFailed, TelephonyConnection created as null, "
+ + "ignoring.");
+ return;
+ }
+
+ // We have to do all of this work because in some cases, hanging up the call maps to
+ // different underlying signaling (CDMA), which is already encapsulated in
+ // TelephonyConnection.
+ connection.onReject();
+ connection.close();
+ }
+
+ @Override
public void triggerConferenceRecalculate() {
if (mTelephonyConferenceController.shouldRecalculate()) {
mTelephonyConferenceController.recalculate();
@@ -1036,8 +1087,8 @@
TelephonyConnection connection =
createConnectionFor(phone, unknownConnection,
!unknownConnection.isIncoming() /* isOutgoing */,
- request.getAccountHandle(), request.getTelecomCallId(),
- request.getAddress(), videoState);
+ request.getAccountHandle(), request.getTelecomCallId()
+ );
if (connection == null) {
return Connection.createCanceledConnection();
@@ -1240,6 +1291,19 @@
phone.getEmergencyNumberTracker().getEmergencyNumber(number);
if (emergencyNumber != null) {
phone.notifyOutgoingEmergencyCall(emergencyNumber);
+ // If we do not support holding ongoing calls for an outgoing emergency call,
+ // disconnect the ongoing calls.
+ if (!shouldHoldForEmergencyCall(phone) && !getAllConnections().isEmpty()) {
+ for (Connection c : getAllConnections()) {
+ if (!c.equals(connection)
+ && c.getState() != Connection.STATE_DISCONNECTED
+ && c instanceof TelephonyConnection) {
+ ((TelephonyConnection) c).hangup(
+ android.telephony.DisconnectCause
+ .OUTGOING_EMERGENCY_CALL_PLACED);
+ }
+ }
+ }
}
originalConnection = phone.dial(number, new ImsPhone.ImsDialArgs.Builder()
.setVideoState(videoState)
@@ -1306,14 +1370,24 @@
}
}
+ private boolean shouldHoldForEmergencyCall(Phone phone) {
+ CarrierConfigManager cfgManager = (CarrierConfigManager)
+ phone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
+ if (cfgManager == null) {
+ // For some reason CarrierConfigManager is unavailable, return default
+ Log.w(this, "shouldHoldForEmergencyCall: couldn't get CarrierConfigManager");
+ return true;
+ }
+ return cfgManager.getConfigForSubId(phone.getSubId()).getBoolean(
+ CarrierConfigManager.KEY_ALLOW_HOLD_CALL_DURING_EMERGENCY_BOOL, true);
+ }
+
private TelephonyConnection createConnectionFor(
Phone phone,
com.android.internal.telephony.Connection originalConnection,
boolean isOutgoing,
PhoneAccountHandle phoneAccountHandle,
- String telecomCallId,
- Uri address,
- int videoState) {
+ String telecomCallId) {
TelephonyConnection returnConnection = null;
int phoneType = phone.getPhoneType();
if (phoneType == TelephonyManager.PHONE_TYPE_GSM) {
@@ -1342,15 +1416,20 @@
private boolean isOriginalConnectionKnown(
com.android.internal.telephony.Connection originalConnection) {
+ return (getConnectionForOriginalConnection(originalConnection) != null);
+ }
+
+ private TelephonyConnection getConnectionForOriginalConnection(
+ com.android.internal.telephony.Connection originalConnection) {
for (Connection connection : getAllConnections()) {
if (connection instanceof TelephonyConnection) {
TelephonyConnection telephonyConnection = (TelephonyConnection) connection;
if (telephonyConnection.getOriginalConnection() == originalConnection) {
- return true;
+ return telephonyConnection;
}
}
}
- return false;
+ return null;
}
/**
@@ -1586,6 +1665,8 @@
// 4)
// Report Slot's PIN/PUK lock status for sorting later.
int simState = mSubscriptionManagerProxy.getSimStateForSlotIdx(i);
+ // Record SimState.
+ status.simState = simState;
if (simState == TelephonyManager.SIM_STATE_PIN_REQUIRED ||
simState == TelephonyManager.SIM_STATE_PUK_REQUIRED) {
status.isLocked = true;
@@ -1631,6 +1712,15 @@
if (o1.hasDialedEmergencyNumber && !o2.hasDialedEmergencyNumber) {
return 1;
}
+ // Sort by non-absent SIM.
+ if (o1.simState == TelephonyManager.SIM_STATE_ABSENT
+ && o2.simState != TelephonyManager.SIM_STATE_ABSENT) {
+ return -1;
+ }
+ if (o2.simState == TelephonyManager.SIM_STATE_ABSENT
+ && o1.simState != TelephonyManager.SIM_STATE_ABSENT) {
+ return 1;
+ }
// First start by seeing if either of the phone slots are locked. If they
// are, then sort by non-locked SIM first. If they are both locked, sort
// by capability instead.
diff --git a/tests/Android.bp b/tests/Android.bp
new file mode 100644
index 0000000..7a59651
--- /dev/null
+++ b/tests/Android.bp
@@ -0,0 +1,42 @@
+//
+// Copyright (C) 2009 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.
+//
+
+android_test {
+ name: "TeleServiceTests",
+
+ srcs: ["src/**/*.java"],
+
+ libs: [
+ "android.test.runner",
+ "telephony-common",
+ "android.test.base",
+ "ims-common",
+ ],
+ platform_apis: true,
+ certificate: "platform",
+
+ instrumentation_for: "TeleService",
+
+ static_libs: [
+ "androidx.test.rules",
+ "mockito-target-minus-junit4",
+ "androidx.test.espresso.core",
+ "truth-prebuilt",
+ ],
+
+ test_suites: ["device-tests"],
+
+}
diff --git a/tests/Android.mk b/tests/Android.mk
deleted file mode 100644
index a8bd204..0000000
--- a/tests/Android.mk
+++ /dev/null
@@ -1,41 +0,0 @@
-#
-# Copyright (C) 2009 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_PACKAGE_NAME := TeleServiceTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_JAVA_LIBRARIES := telephony-common android.test.base ims-common
-
-LOCAL_INSTRUMENTATION_FOR := TeleService
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- androidx.test.rules \
- mockito-target-minus-junit4 \
- androidx.test.espresso.core \
- truth-prebuilt
-
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/src/com/android/phone/CallFeaturesSettingTest.java b/tests/src/com/android/phone/CallFeaturesSettingTest.java
index 15d48ba..0666c56 100644
--- a/tests/src/com/android/phone/CallFeaturesSettingTest.java
+++ b/tests/src/com/android/phone/CallFeaturesSettingTest.java
@@ -24,10 +24,10 @@
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;
+import android.app.KeyguardManager;
import android.content.Context;
import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.FlakyTest;
import androidx.test.rule.ActivityTestRule;
import com.android.internal.telephony.IccCard;
@@ -49,18 +49,18 @@
IccCard mMockIccCard;
@Rule
public ActivityTestRule<CallFeaturesSetting> mRule =
- new ActivityTestRule<>(CallFeaturesSetting.class);
+ new ActivityTestRule<>(CallFeaturesSetting.class, false, true);
private CallFeaturesSetting mActivity;
@Before
- public void setUp() {
+ public void setUp() throws Throwable {
MockitoAnnotations.initMocks(this);
mActivity = mRule.getActivity();
Context targetContext = InstrumentationRegistry.getTargetContext();
doReturn(targetContext).when(mMockPhone).getContext();
+ keepScreenOn(mRule, mActivity);
}
- @FlakyTest
@Test
public void onResume_fdnIsAvailable_shouldShowFdnMenu() throws NoSuchFieldException,
IllegalAccessException {
@@ -69,13 +69,12 @@
when(mMockIccCard.getIccFdnAvailable()).thenReturn(true);
getField("mPhone").set(mActivity, mMockPhone);
- mActivity.onResume();
+ mActivity.runOnUiThread(() -> mActivity.onResume());
// Check the FDN menu is displayed.
onView(withText(R.string.fdn)).check(matches(isDisplayed()));
}
- @FlakyTest
@Test
public void onResume_iccCardIsNull_shouldNotShowFdnMenu() throws NoSuchFieldException,
IllegalAccessException {
@@ -83,13 +82,12 @@
when(mMockPhone.getIccCard()).thenReturn(null);
getField("mPhone").set(mActivity, mMockPhone);
- mActivity.onResume();
+ mActivity.runOnUiThread(() -> mActivity.onResume());
// Check the FDN menu is not displayed.
onView(withText(R.string.fdn)).check(doesNotExist());
}
- @FlakyTest
@Test
public void onResume_fdnIsNotAvailable_shouldNotShowFdnMenu() throws NoSuchFieldException,
IllegalAccessException {
@@ -98,7 +96,7 @@
when(mMockIccCard.getIccFdnAvailable()).thenReturn(false);
getField("mPhone").set(mActivity, mMockPhone);
- mActivity.onResume();
+ mActivity.runOnUiThread(() -> mActivity.onResume());
// Check the FDN menu is not displayed.
onView(withText(R.string.fdn)).check(doesNotExist());
@@ -109,4 +107,19 @@
field.setAccessible(true);
return field;
}
+
+ /**
+ * Automatically wake up device to perform tests.
+ */
+ private static void keepScreenOn(ActivityTestRule activityTestRule,
+ final CallFeaturesSetting activity) throws Throwable {
+ activityTestRule.runOnUiThread(() -> {
+ activity.setTurnScreenOn(true);
+ activity.setShowWhenLocked(true);
+ KeyguardManager keyguardManager =
+ activity.getSystemService(KeyguardManager.class);
+ keyguardManager.requestDismissKeyguard(activity, null);
+ });
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+ }
}
diff --git a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
index ab4c067..bcc4fd3 100644
--- a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
+++ b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
@@ -23,11 +23,13 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.content.Context;
import android.net.Uri;
import android.os.AsyncResult;
import android.os.Bundle;
@@ -39,6 +41,7 @@
import android.telephony.TelephonyManager;
import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.InstrumentationRegistry;
import androidx.test.filters.FlakyTest;
import androidx.test.runner.AndroidJUnit4;
@@ -280,6 +283,37 @@
/**
* Prerequisites:
+ * - MSIM Device, only slot 1 inserted and PUK locked
+ * - slot 1 has higher capabilities
+ *
+ * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone because it is the only one
+ * with a SIM inserted (even if it is PUK locked)
+ */
+ @Test
+ @SmallTest
+ public void testSlot1PinLockedAndSlot0Absent() {
+ Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
+ false /*isEmergencyOnly*/);
+ Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
+ false /*isEmergencyOnly*/);
+ setDefaultPhone(slot0Phone);
+ setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
+ setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_ABSENT);
+ setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_PIN_REQUIRED);
+ // Slot 1 has more capabilities
+ setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_GSM);
+ setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE);
+ // Slot 1 has SIM inserted.
+ setSlotHasIccCard(SLOT_0_PHONE_ID, false /*isInserted*/);
+ setSlotHasIccCard(SLOT_1_PHONE_ID, true /*isInserted*/);
+
+ Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
+
+ assertEquals(slot1Phone, resultPhone);
+ }
+
+ /**
+ * Prerequisites:
* - MSIM Device, two slots with SIMs inserted
* - Slot 1 is LTE capable, Slot 0 is GSM capable
*
@@ -770,6 +804,11 @@
Phone phone = c.getPhone();
c.setOriginalConnection(c.getOriginalConnection());
+ // Use a real context since the method SubscriptionManager.getResourcesForSubId()
+ // needs to interact with a real context.
+ Context targetContext = InstrumentationRegistry.getTargetContext();
+ doReturn(targetContext).when(phone).getContext();
+
// When the registration occurs, we'll capture the handler and message so we can post our
// own messages to it.
ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);