Merge "Conference's connections use participants' own connect time if available."
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index ce774d8..9f9269e 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -22,10 +22,6 @@
android:sharedUserLabel="@string/phoneAppLabel"
>
- <uses-sdk
- android:minSdkVersion="23"
- android:targetSdkVersion="26" />
-
<original-package android:name="com.android.phone" />
<protected-broadcast android:name="android.telecom.action.TTY_PREFERRED_MODE_CHANGED" />
@@ -92,6 +88,10 @@
<protected-broadcast android:name= "android.telephony.action.SIM_SLOT_STATUS_CHANGED" />
<protected-broadcast android:name= "android.telephony.action.SUBSCRIPTION_CARRIER_IDENTITY_CHANGED" />
<protected-broadcast android:name= "android.telephony.action.SUBSCRIPTION_PRECISE_CARRIER_IDENTITY_CHANGED" />
+ <protected-broadcast android:name= "android.telephony.action.NETWORK_COUNTRY_CHANGED" />
+
+ <!-- For Vendor Debugging in Telephony -->
+ <protected-broadcast android:name="android.telephony.debug.action.DEBUG_EVENT" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
<uses-permission android:name="android.permission.CALL_PHONE" />
diff --git a/res/layout/pref_dialog_editpin.xml b/res/layout/pref_dialog_editpin.xml
index a278690..94cdadf 100644
--- a/res/layout/pref_dialog_editpin.xml
+++ b/res/layout/pref_dialog_editpin.xml
@@ -22,7 +22,7 @@
android:orientation="vertical"
android:padding="?android:attr/dialogPreferredPadding">
- <TextView android:id="@+android:id/message"
+ <TextView android:id="@android:id/message"
style="?android:attr/textAppearanceSmall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/res/values/config.xml b/res/values/config.xml
index b1f8ae8..6b6bf04 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -254,6 +254,7 @@
<!-- Intent action to launch target emergency app. -->
<string name="config_emergency_app_intent" translatable="false"></string>
- <!-- Flag indicating whether shortcut view of promoted emergency numbers should be enabled. -->
- <bool name="config_emergency_shortcut_view_enabled">false</bool>
+ <!-- The country list that shortcut view can be enabled. -->
+ <string-array name="config_countries_to_enable_shortcut_view" translatable="false">
+ </string-array>
</resources>
diff --git a/src/com/android/phone/EmergencyDialer.java b/src/com/android/phone/EmergencyDialer.java
index 80b4632..d7443d5 100644
--- a/src/com/android/phone/EmergencyDialer.java
+++ b/src/com/android/phone/EmergencyDialer.java
@@ -810,10 +810,6 @@
}
private boolean canEnableShortcutView(PersistableBundle carrierConfig) {
- if (!getResources().getBoolean(R.bool.config_emergency_shortcut_view_enabled)) {
- // Disables shortcut view by project.
- return false;
- }
if (!carrierConfig.getBoolean(
CarrierConfigManager.KEY_SUPPORT_EMERGENCY_DIALER_SHORTCUT_BOOL)) {
Log.d(LOG_TAG, "Disables shortcut view by carrier requirement");
diff --git a/src/com/android/phone/MobileNetworkSettings.java b/src/com/android/phone/MobileNetworkSettings.java
index 86babd5..465b89a 100644
--- a/src/com/android/phone/MobileNetworkSettings.java
+++ b/src/com/android/phone/MobileNetworkSettings.java
@@ -485,7 +485,7 @@
public void onIntentUpdate(Intent intent) {
if (!mUnavailable) {
- updateCurrentTab(intent);
+ updateCurrentTab(intent.getExtras());
}
}
@@ -583,8 +583,7 @@
}
};
- private int getSlotIdFromIntent(Intent intent) {
- Bundle data = intent.getExtras();
+ private int getSlotIdFromBundle(Bundle data) {
int subId = -1;
if (data != null) {
subId = data.getInt(Settings.EXTRA_SUB_ID, -1);
@@ -754,8 +753,8 @@
mEmptyTabContent);
}
- private void updateCurrentTab(Intent intent) {
- int slotId = getSlotIdFromIntent(intent);
+ private void updateCurrentTab(Bundle data) {
+ int slotId = getSlotIdFromBundle(data);
if (slotId >= 0 && mTabHost != null && mTabHost.getCurrentTab() != slotId) {
mTabHost.setCurrentTab(slotId);
}
@@ -768,6 +767,9 @@
// If advanced fields are already expanded, we save it and expand it
// when it's re-created.
outState.putBoolean(EXPAND_ADVANCED_FIELDS, mExpandAdvancedFields);
+
+ // Save subId of currently shown tab.
+ outState.putInt(Settings.EXTRA_SUB_ID, mSubId);
}
@Override
@@ -851,7 +853,12 @@
getActivity().setContentView(R.layout.telephony_disallowed_preference_screen);
} else {
initializeSubscriptions();
- updateCurrentTab(getActivity().getIntent());
+
+ if (savedInstanceState != null) {
+ updateCurrentTab(savedInstanceState);
+ } else {
+ updateCurrentTab(getActivity().getIntent().getExtras());
+ }
}
}
diff --git a/src/com/android/phone/PhoneApp.java b/src/com/android/phone/PhoneApp.java
index 333e0ec..df151bf 100644
--- a/src/com/android/phone/PhoneApp.java
+++ b/src/com/android/phone/PhoneApp.java
@@ -19,7 +19,6 @@
import android.app.Application;
import android.os.UserHandle;
-import com.android.phone.ecc.IsoToEccProtobufRepository;
import com.android.services.telephony.TelecomAccountRegistry;
/**
@@ -41,10 +40,5 @@
TelecomAccountRegistry.getInstance(this).setupOnBoot();
}
-
- new Thread(() -> {
- // Preload ECC table in background.
- IsoToEccProtobufRepository.getInstance().loadMappingTable(PhoneApp.this);
- }).start();
}
}
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index ccbb4d0..a5cd06b 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -44,6 +44,7 @@
import android.provider.Settings;
import android.telecom.TelecomManager;
import android.telephony.CarrierConfigManager;
+import android.telephony.DebugEventReporter;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -283,6 +284,9 @@
// getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY_VOICE_CALLS);
if (mCM == null) {
+ // Initialize DebugEventReporter early so that it can be used
+ DebugEventReporter.initialize(this);
+
// Inject telephony component factory if configured using other jars.
XmlResourceParser parser = getResources().getXml(R.xml.telephony_injection);
TelephonyComponentFactory.getInstance().injectTheComponentFactory(parser);
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 5947024..e251516 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -265,6 +265,9 @@
private static final String PREF_CARRIERS_SUBSCRIBER_PREFIX = "carrier_subscriber_";
private static final String PREF_PROVISION_IMS_MMTEL_PREFIX = "provision_ims_mmtel_";
+ // String to store multi SIM allowed
+ private static final String PREF_MULTI_SIM_RESTRICTED = "multisim_restricted";
+
// The AID of ISD-R.
private static final String ISDR_AID = "A0000005591010FFFFFFFF8900000100";
@@ -2816,6 +2819,9 @@
} catch (ImsException e) {
Log.w(LOG_TAG, "IMS isCapable - service unavailable: " + e.getMessage());
return false;
+ } catch (IllegalArgumentException e) {
+ Log.i(LOG_TAG, "isCapable: " + subId + " is inactive, returning false.");
+ return false;
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -3400,7 +3406,7 @@
private int getSlotIndexOrException(int subId) throws IllegalArgumentException {
int slotId = SubscriptionManager.getSlotIndex(subId);
if (!SubscriptionManager.isValidSlotIndex(slotId)) {
- throw new IllegalArgumentException("Invalid Subscription Id.");
+ throw new IllegalArgumentException("Invalid Subscription Id, subId=" + subId);
}
return slotId;
}
@@ -4269,8 +4275,9 @@
*/
@Override
public int getPreferredNetworkType(int subId) {
- TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
- mApp, subId, "getPreferredNetworkType");
+ TelephonyPermissions
+ .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
+ mApp, subId, "getPreferredNetworkType");
final long identity = Binder.clearCallingIdentity();
try {
@@ -6448,4 +6455,83 @@
Binder.restoreCallingIdentity(identity);
}
}
+
+ @Override
+ public void setMultisimCarrierRestriction(boolean isMultisimCarrierRestricted) {
+ enforceModifyPermission();
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mTelephonySharedPreferences.edit()
+ .putBoolean(PREF_MULTI_SIM_RESTRICTED, isMultisimCarrierRestricted)
+ .commit();
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public boolean isMultisimCarrierRestricted() {
+ enforceReadPrivilegedPermission("isMultisimCarrierRestricted");
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ // If the device has less than 2 SIM cards, indicate that multisim is restricted.
+ int numPhysicalSlots = UiccController.getInstance().getUiccSlots().length;
+ if (numPhysicalSlots < 2) {
+ loge("isMultisimCarrierRestricted: requires at least 2 cards");
+ return true;
+ }
+
+ // Default value is false. Multi SIM is allowed unless explicitly restricted.
+ return mTelephonySharedPreferences.getBoolean(PREF_MULTI_SIM_RESTRICTED, false);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
+ * Switch configs to enable multi-sim or switch back to single-sim
+ * @param numOfSims number of active sims we want to switch to
+ */
+ @Override
+ public void switchMultiSimConfig(int numOfSims) {
+ TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+ mApp, SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, "switchMultiSimConfig");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mPhoneConfigurationManager.switchMultiSimConfig(numOfSims);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
+ * Get how many sims have been activated on the phone
+ */
+ @Override
+ public int getNumOfActiveSims() {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ return mPhoneConfigurationManager.getNumOfActiveSims();
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
+ * Get whether reboot is required or not after making changes to modem configurations.
+ * Return value defaults to false
+ */
+ @Override
+ public boolean isRebootRequiredForModemConfigChange() {
+ enforceReadPrivilegedPermission("isRebootRequiredForModemConfigChange");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ return mPhoneConfigurationManager.isRebootRequiredForModemConfigChange();
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
}
diff --git a/src/com/android/phone/ShortcutViewUtils.java b/src/com/android/phone/ShortcutViewUtils.java
index 28ee24f..595ea86 100644
--- a/src/com/android/phone/ShortcutViewUtils.java
+++ b/src/com/android/phone/ShortcutViewUtils.java
@@ -96,12 +96,12 @@
return mPromotedEmergencyNumbers;
}
- public boolean isSufficientForEmergencyCall() {
+ public boolean isSufficientForEmergencyCall(@NonNull Context context) {
// Checking mCountryIso because the emergency number list is not reliable to be
// suggested to users if the device didn't camp to any network. In this case, users
// can still try to dial emergency numbers with dial pad.
return mCanPlaceEmergencyCall && mPromotedEmergencyNumbers != null
- && !TextUtils.isEmpty(mCountryIso);
+ && isSupportedCountry(context, mCountryIso);
}
public boolean hasPromotedEmergencyNumber(String number) {
@@ -166,7 +166,7 @@
if (defaultHandle != null) {
PhoneInfo phone = loadPhoneInfo(defaultHandle, telephonyManager, telecomManager,
promotedLists);
- if (phone.isSufficientForEmergencyCall()) {
+ if (phone.isSufficientForEmergencyCall(context)) {
return phone;
}
Log.w(LOG_TAG, "Default PhoneAccount is insufficient for emergency call: "
@@ -181,7 +181,7 @@
for (PhoneAccountHandle handle : allHandles) {
PhoneInfo phone = loadPhoneInfo(handle, telephonyManager, telecomManager,
promotedLists);
- if (phone.isSufficientForEmergencyCall()) {
+ if (phone.isSufficientForEmergencyCall(context)) {
return phone;
} else {
if (Log.isLoggable(LOG_TAG, Log.DEBUG)) {
@@ -196,6 +196,21 @@
return null;
}
+ private static boolean isSupportedCountry(@NonNull Context context, String countryIso) {
+ if (TextUtils.isEmpty(countryIso)) {
+ return false;
+ }
+
+ String[] countrysToEnableShortcutView = context.getResources().getStringArray(
+ R.array.config_countries_to_enable_shortcut_view);
+ for (String supportedCountry : countrysToEnableShortcutView) {
+ if (countryIso.equalsIgnoreCase(supportedCountry)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private static PhoneInfo loadPhoneInfo(@NonNull PhoneAccountHandle handle,
@NonNull TelephonyManager telephonyManager, @NonNull TelecomManager telecomManager,
Map<Integer, List<EmergencyNumber>> promotedLists) {
diff --git a/src/com/android/phone/ecc/CountryEccInfo.java b/src/com/android/phone/ecc/CountryEccInfo.java
deleted file mode 100644
index 969901d..0000000
--- a/src/com/android/phone/ecc/CountryEccInfo.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2018 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.ecc;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import java.util.Collection;
-
-/**
- * ECC info of a country.
- */
-public class CountryEccInfo {
- private final String mFallbackEcc;
- private final EccInfo[] mEccInfoList;
-
- public CountryEccInfo(String eccFallback, @NonNull Collection<EccInfo> eccInfoList) {
- mFallbackEcc = eccFallback;
- mEccInfoList = eccInfoList.toArray(new EccInfo[eccInfoList.size()]);
- }
-
- /**
- * @return fallback ECC, null if not available.
- */
- public @Nullable String getFallbackEcc() {
- return mFallbackEcc;
- }
-
- public @NonNull EccInfo[] getEccInfoList() {
- return mEccInfoList.clone();
- }
-}
diff --git a/src/com/android/phone/ecc/EccInfo.java b/src/com/android/phone/ecc/EccInfo.java
deleted file mode 100644
index fb41370..0000000
--- a/src/com/android/phone/ecc/EccInfo.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2018 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.ecc;
-
-import androidx.annotation.NonNull;
-
-import java.util.Collection;
-
-/**
- * Emergency call code info.
- */
-public class EccInfo {
- /**
- * ECC Types.
- */
- public enum Type {
- POLICE,
- AMBULANCE,
- FIRE,
- }
-
- private final String mNumber;
- private final Type[] mTypes;
-
- public EccInfo(@NonNull String number, @NonNull Type type) {
- mNumber = number;
- mTypes = new Type[]{ type };
- }
-
- public EccInfo(@NonNull String number, @NonNull Collection<Type> types) {
- mNumber = number;
- mTypes = types.toArray(new Type[types.size()]);
- }
-
- /**
- * @return ECC number.
- */
- public @NonNull String getNumber() {
- return mNumber;
- }
-
- /**
- * Check whether the ECC number has any matches to the target type.
- *
- * @param target The target type to check.
- * @return true if the target matches.
- */
- public boolean containsType(@NonNull Type target) {
- for (Type type : mTypes) {
- if (target.equals(type)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Get the types of the ECC number.
- *
- * @return Copied types array.
- */
- public Type[] getTypes() {
- return mTypes.clone();
- }
-
- /**
- * Get how many types the ECC number is.
- *
- * @return Count of types.
- */
- public int getTypesCount() {
- return mTypes.length;
- }
-}
diff --git a/src/com/android/phone/ecc/IsoToEccProtobufRepository.java b/src/com/android/phone/ecc/IsoToEccProtobufRepository.java
deleted file mode 100644
index 7d9b4f0..0000000
--- a/src/com/android/phone/ecc/IsoToEccProtobufRepository.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (C) 2018 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.ecc;
-
-import android.content.Context;
-import android.os.SystemClock;
-import android.text.TextUtils;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-
-import java.io.BufferedInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.zip.GZIPInputStream;
-
-/**
- * Provides a mapping table from country ISO to ECC info. The data is stored in Protocol Buffers
- * binary format, compressed with GZIP.
- */
-public class IsoToEccProtobufRepository implements IsoToEccRepository {
- private static final String LOG_TAG = "EccRepository";
-
- private static IsoToEccProtobufRepository sInstance;
-
- /**
- * Returns the singleton instance of IsoToEccProtobufRepository
- */
- public static synchronized IsoToEccProtobufRepository getInstance() {
- if (sInstance == null) {
- sInstance = new IsoToEccProtobufRepository();
- }
- return sInstance;
- }
-
- private final Map<String, CountryEccInfo> mEccTable = new HashMap<>();
-
- private IsoToEccProtobufRepository() {
- }
-
- @Override
- @Nullable
- public CountryEccInfo getCountryEccInfo(@NonNull Context context, String iso)
- throws IOException {
- if (TextUtils.isEmpty(iso)) {
- return null;
- }
-
- synchronized (mEccTable) {
- return mEccTable.get(iso.toUpperCase());
- }
- }
-
- /**
- * Loads the mapping table.
- */
- public void loadMappingTable(@NonNull Context context) {
- ProtobufEccData.AllInfo allEccData = null;
-
- long startTime = SystemClock.uptimeMillis();
- try {
- allEccData = parseEccData(new BufferedInputStream(
- context.getAssets().open("eccdata")));
- } catch (IOException e) {
- Log.e(LOG_TAG, "Failed to retrieve ECC: ", e);
- }
- long endTime = SystemClock.uptimeMillis();
-
- if (allEccData == null) {
- return;
- }
-
- if (Log.isLoggable(LOG_TAG, Log.DEBUG)) {
- Log.d(LOG_TAG, "Loading time = " + (endTime - startTime) + "ms"
- + ", Country Count = " + allEccData.getCountriesCount()
- + ", initialized = " + allEccData.isInitialized());
- }
-
- // Converts to run-time data from Protobuf data.
- synchronized (mEccTable) {
- mEccTable.clear();
- for (ProtobufEccData.CountryInfo countryData : allEccData.getCountriesList()) {
- if (countryData.hasIsoCode()) {
- CountryEccInfo countryInfo = loadCountryEccInfo(countryData);
- if (countryInfo != null) {
- mEccTable.put(countryData.getIsoCode().toUpperCase(), countryInfo);
- }
- }
- }
- }
- }
-
- @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
- Map<String, CountryEccInfo> getEccTable() {
- return mEccTable;
- }
-
- private ProtobufEccData.AllInfo parseEccData(InputStream input) throws IOException {
- return ProtobufEccData.AllInfo.parseFrom(new GZIPInputStream(input));
- }
-
- private EccInfo loadEccInfo(String isoCode, ProtobufEccData.EccInfo eccData) {
- String phoneNumber = eccData.getPhoneNumber().trim();
- if (phoneNumber.isEmpty()) {
- Log.i(LOG_TAG, "Discard ecc " + phoneNumber
- + " for " + isoCode + " due to empty phone number");
- return null;
- }
-
- ArraySet<EccInfo.Type> eccTypes = new ArraySet<>(eccData.getTypesCount());
- for (ProtobufEccData.EccInfo.Type typeData : eccData.getTypesList()) {
- switch (typeData) {
- case POLICE:
- eccTypes.add(EccInfo.Type.POLICE);
- break;
- case AMBULANCE:
- eccTypes.add(EccInfo.Type.AMBULANCE);
- break;
- case FIRE:
- eccTypes.add(EccInfo.Type.FIRE);
- break;
- default:
- // Ignores unknown types.
- }
- }
-
- if (eccTypes.isEmpty()) {
- Log.i(LOG_TAG, "Discard ecc " + phoneNumber
- + " for " + isoCode + " due to no valid type");
- return null;
- }
- return new EccInfo(phoneNumber, eccTypes);
- }
-
- private CountryEccInfo loadCountryEccInfo(ProtobufEccData.CountryInfo countryData) {
- ArrayMap<String, EccInfo> eccInfoMap = new ArrayMap<>(countryData.getEccsCount());
- for (ProtobufEccData.EccInfo eccData : countryData.getEccsList()) {
- EccInfo eccInfo = loadEccInfo(countryData.getIsoCode(), eccData);
- String key = eccInfo.getNumber().trim();
- EccInfo existentEccInfo = eccInfoMap.get(key);
- if (existentEccInfo == null) {
- eccInfoMap.put(key, eccInfo);
- } else {
- // Merges types of duplicated ECC info objects.
- ArraySet<EccInfo.Type> eccTypes = new ArraySet<>(
- eccInfo.getTypesCount() + existentEccInfo.getTypesCount());
- for (EccInfo.Type type : eccInfo.getTypes()) {
- eccTypes.add(type);
- }
- for (EccInfo.Type type : existentEccInfo.getTypes()) {
- eccTypes.add(type);
- }
- eccInfoMap.put(key, new EccInfo(eccInfo.getNumber(), eccTypes));
- }
- }
-
- if (eccInfoMap.isEmpty() && !countryData.hasEccFallback()) {
- Log.i(LOG_TAG, "Discard empty data for " + countryData.getIsoCode());
- return null;
- }
- return new CountryEccInfo(countryData.getEccFallback(), eccInfoMap.values());
- }
-}
diff --git a/src/com/android/phone/ecc/IsoToEccRepository.java b/src/com/android/phone/ecc/IsoToEccRepository.java
deleted file mode 100644
index 6d95af4..0000000
--- a/src/com/android/phone/ecc/IsoToEccRepository.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2018 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.ecc;
-
-import android.content.Context;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import java.io.IOException;
-
-/**
- * Data source for country ISO to ECC info list mapping.
- */
-public interface IsoToEccRepository {
- /**
- * Get available emergency numbers for given country ISO. Because the possible of IO wait
- * (depends on the implementation), this method should not be called in the main thread.
- *
- * @param context The context used to access resources.
- * @param iso For which ECC info list is returned.
- * @return The ECC info of given ISO. Null if no match.
- * @throws IOException if an error occurs while initialize the repository or retrieving
- * the {@link CountryEccInfo}.
- */
- @Nullable CountryEccInfo getCountryEccInfo(@NonNull Context context, @Nullable String iso)
- throws IOException;
-}
diff --git a/src/com/android/phone/settings/PhoneAccountSettingsFragment.java b/src/com/android/phone/settings/PhoneAccountSettingsFragment.java
index 670f98d..41063e2 100644
--- a/src/com/android/phone/settings/PhoneAccountSettingsFragment.java
+++ b/src/com/android/phone/settings/PhoneAccountSettingsFragment.java
@@ -18,6 +18,7 @@
import android.telecom.TelecomManager;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
+import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
@@ -76,6 +77,15 @@
private SwitchPreference mSipReceiveCallsPreference;
private SipPreferences mSipPreferences;
+ private final SubscriptionManager.OnSubscriptionsChangedListener
+ mOnSubscriptionsChangeListener =
+ new SubscriptionManager.OnSubscriptionsChangedListener() {
+ @Override
+ public void onSubscriptionsChanged() {
+ updateAccounts();
+ }
+ };
+
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
@@ -122,34 +132,8 @@
*/
mAccountList = (PreferenceCategory) getPreferenceScreen().findPreference(
ACCOUNTS_LIST_CATEGORY_KEY);
- List<PhoneAccountHandle> allNonSimAccounts =
- getCallingAccounts(false /* includeSims */, true /* includeDisabled */);
- // Check to see if we should show the entire section at all.
- if (shouldShowConnectionServiceList(allNonSimAccounts)) {
- List<PhoneAccountHandle> enabledAccounts =
- getCallingAccounts(true /* includeSims */, false /* includeDisabled */);
- // Initialize the account list with the set of enabled & SIM accounts.
- initAccountList(enabledAccounts);
- mDefaultOutgoingAccount = (AccountSelectionPreference)
- getPreferenceScreen().findPreference(DEFAULT_OUTGOING_ACCOUNT_KEY);
- mDefaultOutgoingAccount.setListener(this);
-
- // Only show the 'Make Calls With..." option if there are multiple accounts.
- if (enabledAccounts.size() > 1) {
- updateDefaultOutgoingAccountsModel();
- } else {
- mAccountList.removePreference(mDefaultOutgoingAccount);
- }
-
- Preference allAccounts = getPreferenceScreen().findPreference(ALL_CALLING_ACCOUNTS_KEY);
- // If there are no third party (nonSim) accounts, then don't show enable/disable dialog.
- if (allNonSimAccounts.isEmpty() && allAccounts != null) {
- mAccountList.removePreference(allAccounts);
- }
- } else {
- getPreferenceScreen().removePreference(mAccountList);
- }
+ updateAccounts();
if (isPrimaryUser() && SipUtil.isVoipSupported(getActivity())) {
mSipPreferences = new SipPreferences(getActivity());
@@ -183,6 +167,16 @@
getPreferenceScreen().removePreference(
getPreferenceScreen().findPreference(SIP_SETTINGS_CATEGORY_PREF_KEY));
}
+
+ SubscriptionManager.from(getActivity()).addOnSubscriptionsChangedListener(
+ mOnSubscriptionsChangeListener);
+ }
+
+ @Override
+ public void onPause() {
+ SubscriptionManager.from(getActivity()).removeOnSubscriptionsChangedListener(
+ mOnSubscriptionsChangeListener);
+ super.onPause();
}
/**
@@ -391,6 +385,44 @@
return mTelephonyManager.isMultiSimEnabled() || allNonSimAccounts.size() > 0;
}
+ private void updateAccounts() {
+ if (mAccountList != null) {
+ mAccountList.removeAll();
+ List<PhoneAccountHandle> allNonSimAccounts =
+ getCallingAccounts(false /* includeSims */, true /* includeDisabled */);
+ // Check to see if we should show the entire section at all.
+ if (shouldShowConnectionServiceList(allNonSimAccounts)) {
+ List<PhoneAccountHandle> enabledAccounts =
+ getCallingAccounts(true /* includeSims */, false /* includeDisabled */);
+ // Initialize the account list with the set of enabled & SIM accounts.
+ initAccountList(enabledAccounts);
+
+ mDefaultOutgoingAccount = (AccountSelectionPreference)
+ getPreferenceScreen().findPreference(DEFAULT_OUTGOING_ACCOUNT_KEY);
+ if (mDefaultOutgoingAccount != null) {
+ mDefaultOutgoingAccount.setListener(this);
+
+ // Only show the 'Make Calls With..." option if there are multiple accounts.
+ if (enabledAccounts.size() > 1) {
+ updateDefaultOutgoingAccountsModel();
+ } else {
+ mAccountList.removePreference(mDefaultOutgoingAccount);
+ }
+ }
+
+ Preference allAccounts =
+ getPreferenceScreen().findPreference(ALL_CALLING_ACCOUNTS_KEY);
+ // If there are no third party (nonSim) accounts,
+ // then don't show enable/disable dialog.
+ if (allNonSimAccounts.isEmpty() && allAccounts != null) {
+ mAccountList.removePreference(allAccounts);
+ }
+ } else {
+ getPreferenceScreen().removePreference(mAccountList);
+ }
+ }
+ }
+
private List<PhoneAccountHandle> getCallingAccounts(
boolean includeSims, boolean includeDisabledAccounts) {
PhoneAccountHandle emergencyAccountHandle = getEmergencyPhoneAccount();
diff --git a/src/com/android/services/telephony/TelecomAccountRegistry.java b/src/com/android/services/telephony/TelecomAccountRegistry.java
index 37c5d7c..f925dd6 100644
--- a/src/com/android/services/telephony/TelecomAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecomAccountRegistry.java
@@ -46,6 +46,7 @@
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
import android.telephony.TelephonyManager;
+import android.telephony.ims.ImsException;
import android.telephony.ims.ImsMmTelManager;
import android.telephony.ims.feature.MmTelFeature;
import android.telephony.ims.stub.ImsRegistrationImplBase;
@@ -114,10 +115,10 @@
}
try {
- mMmTelManager = ImsMmTelManager.createForSubscriptionId(mContext, getSubId());
+ mMmTelManager = ImsMmTelManager.createForSubscriptionId(getSubId());
} catch (IllegalArgumentException e) {
Log.i(this, "Not registering MmTel capabilities listener because the subid '"
- + getSubId() + "' is invalid");
+ + getSubId() + "' is invalid: " + e.getMessage());
return;
}
@@ -151,9 +152,13 @@
try {
mMmTelManager.registerMmTelCapabilityCallback(mContext.getMainExecutor(),
mMmtelCapabilityCallback);
- } catch (IllegalStateException e) {
+ } catch (ImsException e) {
Log.w(this, "registerMmTelCapabilityCallback: registration failed, no ImsService"
- + " available.");
+ + " available. Exception: " + e.getMessage());
+ return;
+ } catch (IllegalArgumentException e) {
+ Log.w(this, "registerMmTelCapabilityCallback: registration failed, invalid"
+ + " subscription, Exception" + e.getMessage());
return;
}
}
@@ -316,6 +321,8 @@
&& isImsVoiceAvailable()) {
capabilities |= PhoneAccount.CAPABILITY_RTT;
mIsRttCapable = true;
+ } else {
+ mIsRttCapable = false;
}
extras.putBoolean(PhoneAccount.EXTRA_SUPPORTS_VIDEO_CALLING_FALLBACK,
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index d2ba8f1..3886e58 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -46,6 +46,7 @@
import com.android.internal.telephony.Call;
import com.android.internal.telephony.CallFailCause;
import com.android.internal.telephony.CallStateException;
+import com.android.internal.telephony.Call.HoldingRequestState;
import com.android.internal.telephony.Connection.Capability;
import com.android.internal.telephony.Connection.PostDialListener;
import com.android.internal.telephony.Phone;
@@ -952,6 +953,7 @@
// instead of actually putting it on hold.
if (ringingCall.getState() != Call.State.WAITING) {
phone.switchHoldingAndActive();
+ mOriginalConnection.getCall().updateHoldingRequestState(HoldingRequestState.STARTED);
}
// TODO: Cdma calls are slightly different.
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index ab9e211..e0db44e 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -71,6 +71,8 @@
import java.util.Queue;
import java.util.regex.Pattern;
+import javax.annotation.Nullable;
+
/**
* Service for making GSM and CDMA connections.
*/
@@ -321,8 +323,8 @@
if (PhoneAccount.SCHEME_VOICEMAIL.equals(scheme)) {
// TODO: We don't check for SecurityException here (requires
// CALL_PRIVILEGED permission).
- final Phone phone = getPhoneForAccount(request.getAccountHandle(), false,
- handle.getSchemeSpecificPart());
+ final Phone phone = getPhoneForAccount(request.getAccountHandle(),
+ false /* isEmergencyCall */, null /* not an emergency call */);
if (phone == null) {
Log.d(this, "onCreateOutgoingConnection, phone is null");
return Connection.createFailedConnection(
@@ -360,8 +362,8 @@
"Unable to parse number"));
}
- final Phone phone = getPhoneForAccount(request.getAccountHandle(), false,
- handle.getSchemeSpecificPart());
+ final Phone phone = getPhoneForAccount(request.getAccountHandle(),
+ false /* isEmergencyCall*/, null /* not an emergency call */);
if (phone != null && CDMA_ACTIVATION_CODE_REGEX_PATTERN.matcher(number).matches()) {
// Obtain the configuration for the outgoing phone's SIM. If the outgoing number
// matches the *228 regex pattern, fail the call. This number is used for OTASP, and
@@ -468,7 +470,8 @@
// Get the right phone object from the account data passed in.
final Phone phone = getPhoneForAccount(request.getAccountHandle(), isEmergencyNumber,
- handle.getSchemeSpecificPart());
+ /* Note: when not an emergency, handle can be null for unknown callers */
+ handle == null ? null : handle.getSchemeSpecificPart());
Connection resultConnection = getTelephonyConnection(request, numberToDial,
isEmergencyNumber, handle, phone);
// If there was a failure, the resulting connection will not be a TelephonyConnection,
@@ -512,8 +515,9 @@
if (isRadioReady) {
// Get the right phone object since the radio has been turned on
// successfully.
- final Phone phone = getPhoneForAccount(request.getAccountHandle(),
- isEmergencyNumber, handle.getSchemeSpecificPart());
+ final Phone phone = getPhoneForAccount(request.getAccountHandle(), isEmergencyNumber,
+ /* Note: when not an emergency, handle can be null for unknown callers */
+ handle == null ? null : handle.getSchemeSpecificPart());
// If the PhoneType of the Phone being used is different than the Default Phone, then we
// need create a new Connection using that PhoneType and replace it in Telecom.
if (phone.getPhoneType() != originalPhoneType) {
@@ -732,7 +736,8 @@
isEmergency = true;
}
Phone phone = getPhoneForAccount(accountHandle, isEmergency,
- request.getAddress().getSchemeSpecificPart());
+ /* Note: when not an emergency, handle can be null for unknown callers */
+ request.getAddress() == null ? null : request.getAddress().getSchemeSpecificPart());
if (phone == null) {
return Connection.createFailedConnection(
DisconnectCauseUtil.toTelecomDisconnectCause(
@@ -844,7 +849,8 @@
isEmergency = true;
}
Phone phone = getPhoneForAccount(accountHandle, isEmergency,
- request.getAddress().getSchemeSpecificPart());
+ /* Note: when not an emergency, handle can be null for unknown callers */
+ request.getAddress() == null ? null : request.getAddress().getSchemeSpecificPart());
if (phone == null) {
return Connection.createFailedConnection(
DisconnectCauseUtil.toTelecomDisconnectCause(
@@ -1234,8 +1240,17 @@
return false;
}
+ /**
+ * Determines which {@link Phone} will be used to place the call.
+ * @param accountHandle The {@link PhoneAccountHandle} which was sent from Telecom to place the
+ * call on.
+ * @param isEmergency {@code true} if this is an emergency call, {@code false} otherwise.
+ * @param emergencyNumberAddress When {@code isEmergency} is {@code true}, will be the phone
+ * of the emergency call. Otherwise, this can be {@code null} .
+ * @return
+ */
private Phone getPhoneForAccount(PhoneAccountHandle accountHandle, boolean isEmergency,
- String emergencyNumberAddress) {
+ @Nullable String emergencyNumberAddress) {
Phone chosenPhone = null;
int subId = PhoneUtils.getSubIdForPhoneAccountHandle(accountHandle);
if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
diff --git a/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/ImsCallingActivity.java b/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/ImsCallingActivity.java
index fea2bf8..0ff6cc1 100644
--- a/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/ImsCallingActivity.java
+++ b/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/ImsCallingActivity.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.os.Bundle;
import android.telephony.SubscriptionManager;
+import android.telephony.ims.ImsException;
import android.telephony.ims.ImsMmTelManager;
import android.telephony.ims.feature.MmTelFeature;
import android.telephony.ims.stub.ImsRegistrationImplBase;
@@ -162,12 +163,12 @@
mListView = (ListView) findViewById(R.id.cap_cb_list);
mListView.setAdapter(mCapabiltyEventAdapter);
try {
- mImsManager = ImsMmTelManager.createForSubscriptionId(this,
+ mImsManager = ImsMmTelManager.createForSubscriptionId(
SubscriptionManager.getDefaultVoiceSubscriptionId());
Log.i("ImsCallingActivity", "onResume");
mImsManager.registerMmTelCapabilityCallback(getMainExecutor(), mCapabilityCallback);
- } catch (IllegalArgumentException e) {
- Log.w("ImsCallingActivity", "illegal subscription ID.");
+ } catch (IllegalArgumentException | ImsException e) {
+ Log.w("ImsCallingActivity", "Exception: " + e.getMessage());
}
}
diff --git a/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/ImsRegistrationActivity.java b/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/ImsRegistrationActivity.java
index 3317ff1..e4a4e6f 100644
--- a/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/ImsRegistrationActivity.java
+++ b/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/ImsRegistrationActivity.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.os.Bundle;
import android.telephony.SubscriptionManager;
+import android.telephony.ims.ImsException;
import android.telephony.ims.ImsMmTelManager;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.stub.ImsRegistrationImplBase;
@@ -177,10 +178,10 @@
mListView = (ListView) findViewById(R.id.reg_cb_list);
mListView.setAdapter(mRegItemAdapter);
try {
- mImsManager = ImsMmTelManager.createForSubscriptionId(this,
+ mImsManager = ImsMmTelManager.createForSubscriptionId(
SubscriptionManager.getDefaultVoiceSubscriptionId());
mImsManager.registerImsRegistrationCallback(getMainExecutor(), mRegistrationCallback);
- } catch (IllegalArgumentException e) {
+ } catch (IllegalArgumentException | ImsException e) {
Log.w("ImsCallingActivity", "illegal subscription ID.");
}
diff --git a/testapps/TelephonyRegistryTestApp/AndroidManifest.xml b/testapps/TelephonyRegistryTestApp/AndroidManifest.xml
index 708ea66..1cfd3ba 100644
--- a/testapps/TelephonyRegistryTestApp/AndroidManifest.xml
+++ b/testapps/TelephonyRegistryTestApp/AndroidManifest.xml
@@ -19,6 +19,7 @@
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
+ <uses-permission android:name="android.permission.READ_PRECISE_PHONE_STATE"/>
<application android:label="TelephonyRegistryTestApp">
<activity
android:name=".TelephonyRegistryTestApp"