Merge "Avoid duplicate carrier config change bcast." into mnc-dev
diff --git a/sip/src/com/android/services/telephony/sip/SipConnection.java b/sip/src/com/android/services/telephony/sip/SipConnection.java
index 5df61b7..e9f8e05 100644
--- a/sip/src/com/android/services/telephony/sip/SipConnection.java
+++ b/sip/src/com/android/services/telephony/sip/SipConnection.java
@@ -132,7 +132,8 @@
public void onHold() {
if (VERBOSE) log("onHold");
try {
- if (getPhone() != null && getState() == STATE_ACTIVE) {
+ if (getPhone() != null && getState() == STATE_ACTIVE
+ && getPhone().getRingingCall().getState() != Call.State.WAITING) {
getPhone().switchHoldingAndActive();
}
} catch (CallStateException e) {
diff --git a/sip/src/com/android/services/telephony/sip/SipConnectionService.java b/sip/src/com/android/services/telephony/sip/SipConnectionService.java
index ae21d73..ab4223a 100644
--- a/sip/src/com/android/services/telephony/sip/SipConnectionService.java
+++ b/sip/src/com/android/services/telephony/sip/SipConnectionService.java
@@ -110,8 +110,8 @@
if (attemptCall) {
// The ID used for SIP-based phone account is the SIP profile Uri. Use it to find
// the actual profile.
- String profileUri = accountHandle.getId();
- findProfile(profileUri, new IProfileFinderCallback() {
+ String profileName = accountHandle.getId();
+ findProfile(profileName, new IProfileFinderCallback() {
@Override
public void onFound(SipProfile profile) {
if (profile == null) {
@@ -205,7 +205,7 @@
* in communicating with the database, so it is done asynchronously with a separate thread and a
* callback interface.
*/
- private void findProfile(final String profileUri, final IProfileFinderCallback callback) {
+ private void findProfile(final String profileName, final IProfileFinderCallback callback) {
if (VERBOSE) log("findProfile");
new Thread(new Runnable() {
@Override
@@ -214,7 +214,7 @@
List<SipProfile> profileList = mSipProfileDb.retrieveSipProfileList();
if (profileList != null) {
for (SipProfile profile : profileList) {
- if (Objects.equals(profileUri, profile.getUriString())) {
+ if (Objects.equals(profileName, profile.getProfileName())) {
profileToUse = profile;
break;
}
diff --git a/src/com/android/phone/common/mail/MailTransport.java b/src/com/android/phone/common/mail/MailTransport.java
index c66130c..99f0272 100644
--- a/src/com/android/phone/common/mail/MailTransport.java
+++ b/src/com/android/phone/common/mail/MailTransport.java
@@ -16,6 +16,7 @@
package com.android.phone.common.mail;
import android.content.Context;
+import android.net.Network;
import com.android.phone.common.mail.store.ImapStore;
import com.android.phone.common.mail.utils.LogUtils;
@@ -51,6 +52,7 @@
HttpsURLConnection.getDefaultHostnameVerifier();
private Context mContext;
+ private Network mNetwork;
private String mHost;
private int mPort;
private Socket mSocket;
@@ -58,8 +60,9 @@
private BufferedOutputStream mOut;
private int mFlags;
- public MailTransport(Context context, String address, int port, int flags) {
+ public MailTransport(Context context, Network network, String address, int port, int flags) {
mContext = context;
+ mNetwork = network;
mHost = address;
mPort = port;
mFlags = flags;
@@ -71,7 +74,7 @@
*/
@Override
public MailTransport clone() {
- return new MailTransport(mContext, mHost, mPort, mFlags);
+ return new MailTransport(mContext, mNetwork, mHost, mPort, mFlags);
}
public boolean canTrySslSecurity() {
@@ -94,7 +97,11 @@
if (canTrySslSecurity()) {
mSocket = HttpsURLConnection.getDefaultSSLSocketFactory().createSocket();
} else {
- mSocket = new Socket();
+ if (mNetwork == null) {
+ mSocket = new Socket();
+ } else {
+ mSocket = mNetwork.getSocketFactory().createSocket();
+ }
}
mSocket.connect(socketAddress, SOCKET_CONNECT_TIMEOUT);
// After the socket connects to an SSL server, confirm that the hostname is as expected
diff --git a/src/com/android/phone/common/mail/store/ImapStore.java b/src/com/android/phone/common/mail/store/ImapStore.java
index 1c91e76..605abbb 100644
--- a/src/com/android/phone/common/mail/store/ImapStore.java
+++ b/src/com/android/phone/common/mail/store/ImapStore.java
@@ -17,6 +17,7 @@
package com.android.phone.common.mail.store;
import android.content.Context;
+import android.net.Network;
import com.android.phone.common.mail.internet.MimeMessage;
import com.android.phone.common.mail.MailTransport;
@@ -50,11 +51,11 @@
* Contains all the information necessary to log into an imap server
*/
public ImapStore(Context context, String username, String password, int port,
- String serverName, int flags) {
+ String serverName, int flags, Network network) {
mContext = context;
mUsername = username;
mPassword = password;
- mTransport = new MailTransport(context, serverName, port, flags);
+ mTransport = new MailTransport(context, network, serverName, port, flags);
}
public Context getContext() {
diff --git a/src/com/android/phone/settings/PhoneAccountSettingsFragment.java b/src/com/android/phone/settings/PhoneAccountSettingsFragment.java
index ce738b6..86036ce 100644
--- a/src/com/android/phone/settings/PhoneAccountSettingsFragment.java
+++ b/src/com/android/phone/settings/PhoneAccountSettingsFragment.java
@@ -25,6 +25,8 @@
import android.telephony.TelephonyManager;
import android.util.Log;
+import com.android.internal.telephony.Phone;
+import com.android.phone.PhoneUtils;
import com.android.phone.R;
import com.android.phone.SubscriptionInfoHelper;
import com.android.services.telephony.sip.SipAccountRegistry;
@@ -103,22 +105,56 @@
addPreferencesFromResource(R.xml.phone_account_settings);
+ /**
+ * Here we make decisions about what we will and will not display with regards to phone-
+ * account settings. The basic settings structure is this:
+ * (1) <Make Calls With...> // Lets user pick a default account for outgoing calls
+ * (2) <Account List>
+ * <Account>
+ * ...
+ * <Account>
+ * </Account List>
+ * (3) <All Accounts> // Lets user enable/disable third-party accounts. SIM-based accounts
+ * // are always enabled and so aren't relevant here.
+ *
+ * Here are the rules that we follow:
+ * - (1) is only shown if there are multiple enabled accounts, including SIM accounts.
+ * This can be 2+ SIM accounts, 2+ third party accounts or any combination.
+ * - (2) The account list only lists (a) enabled third party accounts and (b) SIM-based
+ * accounts. However, for single-SIM devices, if the only account to show is the
+ * SIM-based account, we don't show the list at all under the assumption that the user
+ * already knows about the account.
+ * - (3) Is only shown if there exist any third party accounts. If none exist, then the
+ * option is hidden since there is nothing that can be done in it.
+ *
+ * By far, the most common case for users will be the single-SIM device without any
+ * third party accounts. IOW, the great majority of users won't see any of these options.
+ */
mAccountList = (PreferenceCategory) getPreferenceScreen().findPreference(
ACCOUNTS_LIST_CATEGORY_KEY);
- if (shouldShowConnectionServiceList()) {
- initAccountList();
+ 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);
- if (mTelecomManager.getCallCapablePhoneAccounts().size() > 1) {
+
+ // 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 (getNonSimCallingAccounts(true).isEmpty() && allAccounts != null) {
+ // If there are no third party (nonSim) accounts, then don't show enable/disable dialog.
+ if (allNonSimAccounts.isEmpty() && allAccounts != null) {
mAccountList.removePreference(allAccounts);
}
} else {
@@ -296,7 +332,7 @@
private void updateDefaultOutgoingAccountsModel() {
mDefaultOutgoingAccount.setModel(
mTelecomManager,
- mTelecomManager.getCallCapablePhoneAccounts(),
+ getCallingAccounts(true /* includeSims */, false /* includeDisabled */),
mTelecomManager.getUserSelectedOutgoingPhoneAccount(),
getString(R.string.phone_accounts_ask_every_time));
}
@@ -329,20 +365,22 @@
}
}
- private void initAccountList() {
+ private void initAccountList(List<PhoneAccountHandle> enabledAccounts) {
+
boolean isMultiSimDevice = mTelephonyManager.isMultiSimEnabled();
// On a single-SIM device, do not list any accounts if the only account is the SIM-based
// one. This is because on single-SIM devices, we do not expose SIM settings through the
// account listing entry so showing it does nothing to help the user. Nor does the lack of
// action match the "Settings" header above the listing.
- if (!isMultiSimDevice && getNonSimCallingAccounts(false).isEmpty()) {
+ if (!isMultiSimDevice && getCallingAccounts(
+ false /* includeSims */, false /* includeDisabled */).isEmpty()){
return;
}
// Obtain the list of phone accounts.
List<PhoneAccount> accounts = new ArrayList<>();
- for (PhoneAccountHandle handle : mTelecomManager.getCallCapablePhoneAccounts()) {
+ for (PhoneAccountHandle handle : enabledAccounts) {
PhoneAccount account = mTelecomManager.getPhoneAccount(handle);
if (account != null) {
accounts.add(account);
@@ -453,21 +491,29 @@
return null;
}
- private boolean shouldShowConnectionServiceList() {
- return mTelephonyManager.isMultiSimEnabled() ||
- getNonSimCallingAccounts(true).size() > 0;
+ private boolean shouldShowConnectionServiceList(List<PhoneAccountHandle> allNonSimAccounts) {
+ return mTelephonyManager.isMultiSimEnabled() || allNonSimAccounts.size() > 0;
}
- private List<PhoneAccountHandle> getNonSimCallingAccounts(boolean includeDisabledAccounts) {
+ private List<PhoneAccountHandle> getCallingAccounts(
+ boolean includeSims, boolean includeDisabledAccounts) {
+ PhoneAccountHandle emergencyAccountHandle = getEmergencyPhoneAccount();
+
List<PhoneAccountHandle> accountHandles =
mTelecomManager.getCallCapablePhoneAccounts(includeDisabledAccounts);
for (Iterator<PhoneAccountHandle> i = accountHandles.iterator(); i.hasNext();) {
PhoneAccountHandle handle = i.next();
+ if (handle.equals(emergencyAccountHandle)) {
+ // never include emergency call accounts in this piece of code.
+ i.remove();
+ continue;
+ }
+
PhoneAccount account = mTelecomManager.getPhoneAccount(handle);
- if (account == null ||
- (account.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION))) {
- // If the account is no longer valid OR the account is a built-in SIM account,
- // remove!
+ if (account == null) {
+ i.remove();
+ } else if (!includeSims &&
+ account.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
i.remove();
}
}
@@ -477,4 +523,9 @@
private String nullToEmpty(String str) {
return str == null ? "" : str;
}
+
+ private PhoneAccountHandle getEmergencyPhoneAccount() {
+ return PhoneUtils.makePstnPhoneAccountHandleWithPrefix(
+ (Phone) null, "" /* prefix */, true /* isEmergency */);
+ }
}
diff --git a/src/com/android/phone/vvm/omtp/OmtpConstants.java b/src/com/android/phone/vvm/omtp/OmtpConstants.java
index 971d2d6..fa3cb63 100644
--- a/src/com/android/phone/vvm/omtp/OmtpConstants.java
+++ b/src/com/android/phone/vvm/omtp/OmtpConstants.java
@@ -188,4 +188,6 @@
put(RETURN_CODE, RETURN_CODE_VALUES);
}};
+ /** Indicates the client is Google visual voicemail version 1.0. */
+ public static final String CLIENT_TYPE_GOOGLE_10 = "google.vvm.10";
}
diff --git a/src/com/android/phone/vvm/omtp/SimChangeReceiver.java b/src/com/android/phone/vvm/omtp/SimChangeReceiver.java
index 917374c..95fcb24 100644
--- a/src/com/android/phone/vvm/omtp/SimChangeReceiver.java
+++ b/src/com/android/phone/vvm/omtp/SimChangeReceiver.java
@@ -103,7 +103,7 @@
Log.i(TAG, "Requesting VVM activation for subId: " + subId);
SmsManager smsManager = SmsManager.getSmsManagerForSubscriptionId(subId);
OmtpMessageSender messageSender = new OmtpMessageSender(smsManager,
- (short) applicationPort, destinationNumber, null,
+ (short) applicationPort, destinationNumber, OmtpConstants.CLIENT_TYPE_GOOGLE_10,
OmtpConstants.PROTOCOL_VERSION1_1, null);
messageSender.requestVvmActivation(null);
}
diff --git a/src/com/android/phone/vvm/omtp/fetch/FetchVoicemailReceiver.java b/src/com/android/phone/vvm/omtp/fetch/FetchVoicemailReceiver.java
index ae32c27..179fec3 100644
--- a/src/com/android/phone/vvm/omtp/fetch/FetchVoicemailReceiver.java
+++ b/src/com/android/phone/vvm/omtp/fetch/FetchVoicemailReceiver.java
@@ -21,6 +21,10 @@
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
import android.net.Uri;
import android.provider.VoicemailContract;
import android.provider.VoicemailContract.Voicemails;
@@ -28,6 +32,7 @@
import android.text.TextUtils;
import android.util.Log;
+import com.android.phone.PhoneUtils;
import com.android.phone.vvm.omtp.imap.ImapHelper;
import com.android.phone.vvm.omtp.sync.OmtpVvmSyncAccountManager;
@@ -45,12 +50,22 @@
public static final int SOURCE_DATA = 0;
public static final int PHONE_ACCOUNT_ID = 1;
+ // Timeout used to call ConnectivityManager.requestNetwork
+ private static final int NETWORK_REQUEST_TIMEOUT_MILLIS = 60 * 1000;
+
private ContentResolver mContentResolver;
private Uri mUri;
+ private NetworkRequest mNetworkRequest;
+ private OmtpVvmNetworkRequestCallback mNetworkCallback;
+ private Context mContext;
+ private Account mAccount;
+ private String mUid;
+ private ConnectivityManager mConnectivityManager;
@Override
public void onReceive(final Context context, Intent intent) {
if (VoicemailContract.ACTION_FETCH_VOICEMAIL.equals(intent.getAction())) {
+ mContext = context;
mContentResolver = context.getContentResolver();
mUri = intent.getData();
@@ -71,7 +86,7 @@
}
try {
if (cursor.moveToFirst()) {
- final String uid = cursor.getString(SOURCE_DATA);
+ mUid = cursor.getString(SOURCE_DATA);
String accountId = cursor.getString(PHONE_ACCOUNT_ID);
if (TextUtils.isEmpty(accountId)) {
TelephonyManager telephonyManager = (TelephonyManager)
@@ -83,27 +98,71 @@
return;
}
}
- final Account account = new Account(accountId,
+ mAccount = new Account(accountId,
OmtpVvmSyncAccountManager.ACCOUNT_TYPE);
if (!OmtpVvmSyncAccountManager.getInstance(context)
- .isAccountRegistered(account)) {
+ .isAccountRegistered(mAccount)) {
Log.w(TAG, "Account not registered - cannot retrieve message.");
return;
}
- Executor executor = Executors.newCachedThreadPool();
- executor.execute(new Runnable() {
- @Override
- public void run() {
- new ImapHelper(context, account).fetchVoicemailPayload(
- new VoicemailFetchedCallback(context, mUri), uid);
- }
- });
+ int subId = PhoneUtils.getSubIdForPhoneAccountHandle(
+ PhoneUtils.makePstnPhoneAccountHandle(accountId));
+
+ mNetworkRequest = new NetworkRequest.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ .setNetworkSpecifier(Integer.toString(subId))
+ .build();
+ mNetworkCallback = new OmtpVvmNetworkRequestCallback();
+ getConnectivityManager().requestNetwork(
+ mNetworkRequest, mNetworkCallback, NETWORK_REQUEST_TIMEOUT_MILLIS);
}
} finally {
cursor.close();
}
}
}
+
+ private class OmtpVvmNetworkRequestCallback extends ConnectivityManager.NetworkCallback {
+ @Override
+ public void onAvailable(final Network network) {
+ super.onAvailable(network);
+
+ Executor executor = Executors.newCachedThreadPool();
+ executor.execute(new Runnable() {
+ @Override
+ public void run() {
+ new ImapHelper(mContext, mAccount, network).fetchVoicemailPayload(
+ new VoicemailFetchedCallback(mContext, mUri), mUid);
+ releaseNetwork();
+ }
+ });
+ }
+
+ @Override
+ public void onLost(Network network) {
+ super.onLost(network);
+ releaseNetwork();
+ }
+
+ @Override
+ public void onUnavailable() {
+ super.onUnavailable();
+ releaseNetwork();
+ }
+ }
+
+ private void releaseNetwork() {
+ getConnectivityManager().unregisterNetworkCallback(mNetworkCallback);
+ }
+
+ private ConnectivityManager getConnectivityManager() {
+ if (mConnectivityManager == null) {
+ mConnectivityManager = (ConnectivityManager) mContext.getSystemService(
+ Context.CONNECTIVITY_SERVICE);
+ }
+ return mConnectivityManager;
+ }
}
diff --git a/src/com/android/phone/vvm/omtp/imap/ImapHelper.java b/src/com/android/phone/vvm/omtp/imap/ImapHelper.java
index 1368286..0d02700 100644
--- a/src/com/android/phone/vvm/omtp/imap/ImapHelper.java
+++ b/src/com/android/phone/vvm/omtp/imap/ImapHelper.java
@@ -18,6 +18,7 @@
import android.accounts.Account;
import android.accounts.AccountManager;
import android.content.Context;
+import android.net.Network;
import android.telecom.PhoneAccountHandle;
import android.telecom.Voicemail;
@@ -61,7 +62,7 @@
private Context mContext;
private PhoneAccountHandle mPhoneAccount;
- public ImapHelper(Context context, Account account) {
+ public ImapHelper(Context context, Account account, Network network) {
try {
mContext = context;
mPhoneAccount = PhoneUtils.makePstnPhoneAccountHandle(account.name);
@@ -75,7 +76,7 @@
accountManager.getUserData(account, OmtpConstants.IMAP_PORT));
// TODO: determine the security protocol (e.g. ssl, tls, none, etc.)
mImapStore = new ImapStore(
- context, username, password, port, serverName, ImapStore.FLAG_NONE);
+ context, username, password, port, serverName, ImapStore.FLAG_NONE, network);
} catch (NumberFormatException e) {
LogUtils.e(TAG, e, "Could not parse port number");
}
diff --git a/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java b/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java
index 89f69e0..7a2f5ad 100644
--- a/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java
+++ b/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java
@@ -126,11 +126,6 @@
VoicemailContract.Status.CONFIGURATION_STATE_OK,
VoicemailContract.Status.DATA_CHANNEL_STATE_OK,
VoicemailContract.Status.NOTIFICATION_CHANNEL_STATE_OK);
-
- Bundle bundle = new Bundle();
- bundle.putBoolean(OmtpVvmSyncAdapter.SYNC_EXTRAS_DOWNLOAD, true);
- bundle.putBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, true);
- ContentResolver.requestSync(account, VoicemailContract.AUTHORITY, bundle);
}
// Save the IMAP credentials in the corresponding account object so they are
@@ -139,5 +134,10 @@
// Add a phone state listener so that changes to the communication channels can be recorded.
vvmAccountSyncManager.addPhoneStateListener(account);
+
+ Bundle bundle = new Bundle();
+ bundle.putBoolean(OmtpVvmSyncAdapter.SYNC_EXTRAS_DOWNLOAD, true);
+ bundle.putBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, true);
+ ContentResolver.requestSync(account, VoicemailContract.AUTHORITY, bundle);
}
}
diff --git a/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java b/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java
index 2fbeaab..7fb4df2 100644
--- a/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java
+++ b/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java
@@ -80,7 +80,7 @@
@Override
public void onPerformSync(Account account, Bundle extras, String authority,
ContentProviderClient provider, SyncResult syncResult) {
- ImapHelper imapHelper = new ImapHelper(mContext, account);
+ ImapHelper imapHelper = new ImapHelper(mContext, account, null);
VoicemailsQueryHelper queryHelper = new VoicemailsQueryHelper(mContext);
if (extras.getBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, false)) {