Merge "Make changes to Connection in Telecomm API (2/4)" into lmp-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index f668255..dd9b06d 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -436,6 +436,14 @@
</intent-filter>
</activity>
+ <activity android:name=".settings.PhoneAccountSelectionPreferenceActivity"
+ android:label="@string/phone_accounts"
+ android:theme="@style/DialerSettingsLight">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ </intent-filter>
+ </activity>
+
<!-- bluetooth phone service -->
<service android:name="BluetoothPhoneService">
<intent-filter>
@@ -489,7 +497,6 @@
<intent-filter>
<action android:name="android.net.sip.SIP_SERVICE_UP" />
<action android:name="com.android.phone.SIP_INCOMING_CALL" />
- <action android:name="com.android.phone.SIP_ADD_PHONE" />
<action android:name="com.android.phone.SIP_REMOVE_PHONE" />
<action android:name="com.android.phone.SIP_CALL_OPTION_CHANGED" />
</intent-filter>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index ae0a7c1..0cd350b 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -95,6 +95,7 @@
So, (94 - 38)/2 ==> 28dp -->
<dimen name="incoming_call_widget_asset_margin">28dp</dimen>
<!-- Action bar dimensions. Keep in sync with same value in Dialer. -->
- <dimen name="action_bar_height">64dp</dimen>
+ <dimen name="action_bar_height">56dp</dimen>
+ <dimen name="action_bar_elevation">2dp</dimen>
<dimen name="actionbar_contentInsetStart">72dp</dimen>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 0282c76..4ef5c12 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1218,4 +1218,8 @@
<!-- Label for close button in dialog, for video calling setting. -->
<string name="enable_video_calling_dialog_close">Close</string>
+ <!-- Strings used in Settings->Sim cards for each installed Sim. -->
+ <string name="sim_label_emergency_calls">Emergency calls</string>
+ <string name="sim_description_emergency_calls">Emergency calling only</string>
+ <string name="sim_description_default">SIM card, slot: <xliff:g id="slot_id">%s</xliff:g></string>
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 76b100a..afc1bd2 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -242,6 +242,7 @@
<item name="android:background">@color/actionbar_background_color</item>
<item name="android:titleTextStyle">@style/DialtactsActionBarTitleText</item>
<item name="android:height">@dimen/action_bar_height</item>
+ <item name="android:elevation">@dimen/action_bar_elevation</item>
<!-- Empty icon -->
<item name="android:icon">@android:color/transparent</item>
<!-- Shift the title text to the right -->
@@ -250,7 +251,7 @@
<!-- Text in the action bar at the top of the screen. Should be kept in sync with Dialer. -->
<style name="DialtactsActionBarTitleText"
- parent="@android:style/TextAppearance.Holo.Widget.ActionBar.Title">
+ parent="@android:style/TextAppearance.Material.Widget.ActionBar.Title">
<item name="android:textColor">@color/phone_settings_actionbar_text_color</item>
</style>
diff --git a/res/xml/phone_account_selection.xml b/res/xml/phone_account_selection.xml
new file mode 100644
index 0000000..9c5995c
--- /dev/null
+++ b/res/xml/phone_account_selection.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2014 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
+ -->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+ <PreferenceCategory
+ android:key="phone_accounts_list"
+ android:title="@string/phone_accounts_selection_header"
+ android:persistent="true" />
+</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/phone_account_selection_activity.xml b/res/xml/phone_account_selection_activity.xml
new file mode 100644
index 0000000..9425297
--- /dev/null
+++ b/res/xml/phone_account_selection_activity.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2014 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
+ -->
+
+<preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
+ <header
+ android:fragment="com.android.phone.settings.PhoneAccountSelectionPreferenceActivity$PhoneAccountSelectionPreferenceFragment"
+ android:title="@string/phone_accounts" />
+</preference-headers>
\ No newline at end of file
diff --git a/sip/res/values/strings.xml b/sip/res/values/strings.xml
index 8b85ff4..0163a31 100644
--- a/sip/res/values/strings.xml
+++ b/sip/res/values/strings.xml
@@ -86,8 +86,6 @@
<!-- Title of the button to show in a alert dialog. [CHAR LIMIT=NONE] -->
<string name="close_profile">Close</string>
- <!-- Summary of a SIP account in the list of SIP accounts, consists of primary account status and registration status. This string indicates that this SIP account is a primary account and the string placeholder is the registration status, which will be one of the strings with name starting with "registration_status_" below. [CHAR LIMIT=NONE] -->
- <string name="primary_account_summary_with">Primary account. <xliff:g id="registration_status" example="Registering...">%s</xliff:g></string>
<!-- Text of SIP-call registration status, checking current registration status with SIP service [CHAR LIMIT=NONE] -->
<string name="registration_status_checking_status">Checking status...</string>
<!-- Text of SIP-call registration status, registering with SIP server in order to receive calls on this account [CHAR LIMIT=NONE] -->
@@ -135,10 +133,6 @@
<string name="transport_title">Transport type</string>
<!-- Text of the keepalive preference. [CHAR LIMIT=NONE] -->
<string name="send_keepalive_title">Send keep-alive</string>
- <!-- Text of the set-primary preference. Simplified from "Make this my primary account". [CHAR LIMIT=NONE] -->
- <string name="set_primary_title">Set as primary account</string>
- <!-- Text of the set-primary preference summary. [CHAR LIMIT=NONE] -->
- <string name="set_primary_summary">Used for outbound calls</string>
<!-- Text of the advanced settings section. [CHAR LIMIT=NONE] -->
<string name="advanced_settings">Optional settings</string>
<!-- Text of the username used in authentication. [CHAR LIMIT=NONE] -->
@@ -198,7 +192,6 @@
<string translatable="false" name="port">Port</string>
<string translatable="false" name="transport">Protocol</string>
<string translatable="false" name="send_keepalive">SendKeepAlive</string>
- <string translatable="false" name="set_primary">SetPrimary</string>
<string translatable="false" name="advanced_settings_container">advanced settings container</string>
<string translatable="false" name="auth_username">AuthUserName</string>
diff --git a/sip/res/xml/sip_edit.xml b/sip/res/xml/sip_edit.xml
index f091fc1..15e5ce1 100644
--- a/sip/res/xml/sip_edit.xml
+++ b/sip/res/xml/sip_edit.xml
@@ -45,12 +45,6 @@
android:singleLine="true"
android:inputType="textNoSuggestions"/>
- <CheckBoxPreference
- android:key="@string/set_primary"
- android:title="@string/set_primary_title"
- android:persistent="false"
- android:summary="@string/set_primary_summary"/>
-
<PreferenceScreen
android:key="@string/advanced_settings"
android:title="@string/advanced_settings"
diff --git a/sip/src/com/android/services/telephony/sip/SipAccountRegistry.java b/sip/src/com/android/services/telephony/sip/SipAccountRegistry.java
index 6149231..b00acba 100644
--- a/sip/src/com/android/services/telephony/sip/SipAccountRegistry.java
+++ b/sip/src/com/android/services/telephony/sip/SipAccountRegistry.java
@@ -16,21 +16,15 @@
package com.android.services.telephony.sip;
-import android.content.ComponentName;
import android.content.Context;
-import android.net.Uri;
import android.net.sip.SipException;
import android.net.sip.SipManager;
import android.net.sip.SipProfile;
-import android.provider.Settings;
import android.telecomm.PhoneAccount;
import android.telecomm.PhoneAccountHandle;
import android.telecomm.TelecommManager;
import android.util.Log;
-import com.android.phone.R;
-
-import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -50,41 +44,58 @@
return mProfile;
}
- boolean register(SipManager sipManager, Context context) {
- if (VERBOSE) log("register, profile: " + mProfile);
+ /**
+ * Starts the SIP service associated with the SIP profile.
+ *
+ * @param sipManager The SIP manager.
+ * @param context The context.
+ * @param isReceivingCalls {@code True} if the sip service is being started to make and
+ * receive calls. {@code False} if the sip service is being started only for
+ * outgoing calls.
+ * @return {@code True} if the service started successfully.
+ */
+ boolean startSipService(SipManager sipManager, Context context, boolean isReceivingCalls) {
+ if (VERBOSE) log("startSipService, profile: " + mProfile);
try {
- sipManager.open(
- mProfile,
- SipUtil.createIncomingCallPendingIntent(context, mProfile.getUriString()),
- null);
- TelecommManager.from(context).registerPhoneAccount(createPhoneAccount(context));
+ // Stop the Sip service for the profile if it is already running. This is important
+ // if we are changing the state of the "receive calls" option.
+ sipManager.close(mProfile.getUriString());
+
+ // Start the sip service for the profile.
+ if (isReceivingCalls) {
+ sipManager.open(
+ mProfile,
+ SipUtil.createIncomingCallPendingIntent(context,
+ mProfile.getUriString()),
+ null);
+ } else {
+ sipManager.open(mProfile);
+ }
return true;
} catch (SipException e) {
- log("register, profile: " + mProfile.getProfileName() +
+ log("startSipService, profile: " + mProfile.getProfileName() +
", exception: " + e);
}
return false;
}
- private PhoneAccount createPhoneAccount(Context context) {
- boolean useSipForPstnCalls = useSipForPstnCalls(context);
-
- PhoneAccountHandle accountHandle =
- SipUtil.createAccountHandle(context, mProfile.getUriString());
- List supportedUriSchemes = Arrays.asList(PhoneAccount.SCHEME_SIP);
- if (useSipForPstnCalls) {
- supportedUriSchemes.add(PhoneAccount.SCHEME_TEL);
+ /**
+ * Stops the SIP service associated with the SIP profile. The {@code SipAccountRegistry} is
+ * informed when the service has been stopped via an intent which triggers
+ * {@link SipAccountRegistry#removeSipProfile(String)}.
+ *
+ * @param sipManager The SIP manager.
+ * @return {@code True} if stop was successful.
+ */
+ boolean stopSipService(SipManager sipManager) {
+ try {
+ sipManager.close(mProfile.getUriString());
+ return true;
+ } catch (Exception e) {
+ log("stopSipService, stop failed for profile: " + mProfile.getUriString() +
+ ", exception: " + e);
}
-
- PhoneAccount.Builder builder = PhoneAccount.builder(
- accountHandle, mProfile.getDisplayName())
- .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
- .setAddress(Uri.parse(mProfile.getUriString()))
- .setShortDescription(mProfile.getDisplayName())
- .setIconResId(R.drawable.ic_dialer_sip_black_24dp)
- .setSupportedUriSchemes(supportedUriSchemes);
-
- return builder.build();
+ return false;
}
}
@@ -101,84 +112,174 @@
}
void setup(Context context) {
- clearCurrentSipAccounts(context);
- registerProfiles(context, null);
+ startSipProfilesAsync((Context) context, (String) null);
}
- void addPhone(Context context, String sipUri) {
- registerProfiles(context, sipUri);
+ /**
+ * Starts the SIP service for the specified SIP profile and ensures it has a valid registered
+ * {@link PhoneAccount}.
+ *
+ * @param context The context.
+ * @param sipUri The Uri of the {@link SipProfile} to start, or {@code null} for all.
+ */
+ void startSipService(Context context, String sipUri) {
+ startSipProfilesAsync((Context) context, (String) sipUri);
}
- void removePhone(Context context, String sipUri) {
- for (AccountEntry entry : mAccounts) {
- if (Objects.equals(sipUri, entry.getProfile().getUriString())) {
- TelecommManager.from(context).unregisterPhoneAccount(
- SipUtil.createAccountHandle(context, sipUri));
- mAccounts.remove(entry);
- break;
- }
+ /**
+ * Removes a {@link SipProfile} from the account registry. Does not stop/close the associated
+ * SIP service (this method is invoked via an intent from the SipService once a profile has
+ * been stopped/closed).
+ *
+ * @param sipUri The Uri of the {@link SipProfile} to remove from the registry.
+ */
+ void removeSipProfile(String sipUri) {
+ AccountEntry accountEntry = getAccountEntry(sipUri);
+
+ if (accountEntry != null) {
+ mAccounts.remove(accountEntry);
}
}
/**
+ * Stops a SIP profile and un-registers its associated {@link android.telecomm.PhoneAccount}.
+ * Called after a SIP profile is deleted. The {@link AccountEntry} will be removed when the
+ * service has been stopped. The {@code SipService} fires the {@code ACTION_SIP_REMOVE_PHONE}
+ * intent, which triggers {@link SipAccountRegistry#removeSipProfile(String)} to perform the
+ * removal.
+ *
+ * @param context The context.
+ * @param sipUri The {@code Uri} of the sip profile.
+ */
+ void stopSipService(Context context, String sipUri) {
+ // Stop the sip service for the profile.
+ AccountEntry accountEntry = getAccountEntry(sipUri);
+ if (accountEntry != null ) {
+ SipManager sipManager = SipManager.newInstance(context);
+ accountEntry.stopSipService(sipManager);
+ }
+
+ // Un-register its PhoneAccount.
+ PhoneAccountHandle handle = SipUtil.createAccountHandle(context, sipUri);
+ TelecommManager.from(context).unregisterPhoneAccount(handle);
+ }
+
+ /**
+ * Causes the SIP service to be restarted for all {@link SipProfile}s. For example, if the user
+ * toggles the "receive calls" option for SIP, this method handles restarting the SIP services
+ * in the new mode.
+ *
+ * @param context The context.
+ */
+ void restartSipService(Context context) {
+ startSipProfiles(context, null);
+ }
+
+ /**
+ * Performs an asynchronous call to
+ * {@link SipAccountRegistry#startSipProfiles(android.content.Context, String)}, starting the
+ * specified SIP profile and registering its {@link android.telecomm.PhoneAccount}.
+ *
+ * @param context The context.
+ * @param sipUri A specific SIP uri to start.
+ */
+ private void startSipProfilesAsync(final Context context, final String sipUri) {
+ if (VERBOSE) log("startSipProfiles, start auto registration");
+
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ startSipProfiles(context, sipUri);
+ }}
+ ).start();
+ }
+
+ /**
* Loops through all SIP accounts from the SIP database, starts each service and registers
* each with the telecomm framework. If a specific sipUri is specified, this will only register
* the associated SIP account.
*
+ * Also handles migration from using the primary account shared preference to indicate the
+ * {@link SipProfile} to be used for outgoing Sip connections to using the enabled flag on
+ * {@link android.telecomm.PhoneAccount}s to indicate which profiles can be used for outgoing
+ * or ingoing calls.
+ *
* @param context The context.
- * @param sipUri A specific SIP uri to register.
+ * @param sipUri A specific SIP uri to start, or {@code null} to start all.
*/
- private void registerProfiles(final Context context, final String sipUri) {
- if (VERBOSE) log("registerProfiles, start auto registration");
+ private void startSipProfiles(Context context, String sipUri) {
final SipSharedPreferences sipSharedPreferences = new SipSharedPreferences(context);
- new Thread(new Runnable() {
- @Override
- public void run() {
- SipManager sipManager = SipManager.newInstance(context);
- SipProfileDb profileDb = new SipProfileDb(context);
- String primaryProfile = sipSharedPreferences.getPrimaryAccount();
- List<SipProfile> sipProfileList = profileDb.retrieveSipProfileList();
-
- for (SipProfile profile : sipProfileList) {
- boolean isPrimaryProfile = profile.getUriString().equals(primaryProfile);
- if (profile.getAutoRegistration() || isPrimaryProfile) {
- if (sipUri == null || Objects.equals(sipUri, profile.getUriString())) {
- registerAccountForProfile(profile, sipManager, context);
- }
- }
- }
- }}
- ).start();
- }
-
- private void registerAccountForProfile(
- SipProfile profile, SipManager sipManager, Context context) {
- AccountEntry entry = new AccountEntry(profile);
-
- if (entry.register(sipManager, context)) {
- mAccounts.add(entry);
- }
- }
-
- private void clearCurrentSipAccounts(Context context) {
- ComponentName sipComponentName = new ComponentName(context, SipConnectionService.class);
+ boolean isReceivingCalls = sipSharedPreferences.isReceivingCallsEnabled();
+ String primaryProfile = sipSharedPreferences.getPrimaryAccount();
TelecommManager telecommManager = TelecommManager.from(context);
- List<PhoneAccountHandle> accountHandles = telecommManager.getEnabledPhoneAccounts();
- for (PhoneAccountHandle handle : accountHandles) {
- if (sipComponentName.equals(handle.getComponentName())) {
- telecommManager.unregisterPhoneAccount(handle);
+ SipManager sipManager = SipManager.newInstance(context);
+ SipProfileDb profileDb = new SipProfileDb(context);
+ List<SipProfile> sipProfileList = profileDb.retrieveSipProfileList();
+
+ for (SipProfile profile : sipProfileList) {
+ // Register a PhoneAccount for the profile and optionally enable the primary
+ // profile.
+ if (sipUri == null || Objects.equals(sipUri, profile.getUriString())) {
+ PhoneAccount phoneAccount = SipUtil.createPhoneAccount(context, profile);
+ telecommManager.registerPhoneAccount(phoneAccount);
+
+ // If this profile was the primary profile in the past, mark it as enabled.
+ boolean isPrimaryProfile = primaryProfile != null &&
+ profile.getUriString().equals(primaryProfile);
+ if (isPrimaryProfile) {
+ telecommManager.setPhoneAccountEnabled(
+ phoneAccount.getAccountHandle(), true);
+ }
}
+
+ // Start the SIP service for the profile.
+ if (SipUtil.isPhoneAccountEnabled(context, profile)) {
+ if (sipUri == null || Objects.equals(sipUri, profile.getUriString())) {
+ startSipServiceForProfile(profile, sipManager, context, isReceivingCalls);
+ }
+ }
+ }
+
+ if (primaryProfile != null) {
+ // Remove the primary account shared preference, ensuring the migration does not
+ // occur again in the future.
+ sipSharedPreferences.cleanupPrimaryAccountSetting();
}
}
/**
- * Determines if the user has chosen to use SIP for PSTN calls as well as SIP calls.
+ * Starts the SIP service for a sip profile and saves a new {@code AccountEntry} in the
+ * registry.
+ *
+ * @param profile The {@link SipProfile} to start.
+ * @param sipManager The SIP manager.
* @param context The context.
- * @return {@code True} if SIP should be used for PSTN calls.
+ * @param isReceivingCalls {@code True} if the profile should be started such that it can
+ * receive incoming calls.
*/
- private boolean useSipForPstnCalls(Context context) {
- final SipSharedPreferences sipSharedPreferences = new SipSharedPreferences(context);
- return sipSharedPreferences.getSipCallOption().equals(Settings.System.SIP_ALWAYS);
+ private void startSipServiceForProfile(SipProfile profile, SipManager sipManager,
+ Context context, boolean isReceivingCalls) {
+ removeSipProfile(profile.getUriString());
+
+ AccountEntry entry = new AccountEntry(profile);
+ if (entry.startSipService(sipManager, context, isReceivingCalls)) {
+ mAccounts.add(entry);
+ }
+ }
+
+ /**
+ * Retrieves the {@link AccountEntry} from the registry with the specified Uri.
+ *
+ * @param sipUri The Uri of the profile to retrieve.
+ * @return The {@link AccountEntry}, or {@code null} is it was not found.
+ */
+ private AccountEntry getAccountEntry(String sipUri) {
+ for (AccountEntry entry : mAccounts) {
+ if (Objects.equals(sipUri, entry.getProfile().getUriString())) {
+ return entry;
+ }
+ }
+ return null;
}
private void log(String message) {
diff --git a/sip/src/com/android/services/telephony/sip/SipBroadcastReceiver.java b/sip/src/com/android/services/telephony/sip/SipBroadcastReceiver.java
index a113805..35c07a1 100644
--- a/sip/src/com/android/services/telephony/sip/SipBroadcastReceiver.java
+++ b/sip/src/com/android/services/telephony/sip/SipBroadcastReceiver.java
@@ -47,14 +47,10 @@
} else if (action.equals(SipManager.ACTION_SIP_SERVICE_UP) ||
action.equals(SipManager.ACTION_SIP_CALL_OPTION_CHANGED)) {
sipAccountRegistry.setup(context);
- } else if (action.equals(SipManager.ACTION_SIP_ADD_PHONE)) {
- if (VERBOSE) log("SIP_ADD_PHONE " + intent.getStringExtra(SipManager.EXTRA_LOCAL_URI));
- sipAccountRegistry.addPhone(context, intent.getStringExtra(SipManager.EXTRA_LOCAL_URI));
} else if (action.equals(SipManager.ACTION_SIP_REMOVE_PHONE)) {
if (VERBOSE) log("SIP_REMOVE_PHONE " +
- intent.getStringExtra(SipManager.EXTRA_LOCAL_URI));
- sipAccountRegistry.removePhone(
- context, intent.getStringExtra(SipManager.EXTRA_LOCAL_URI));
+ intent.getStringExtra(SipManager.EXTRA_LOCAL_URI));
+ sipAccountRegistry.removeSipProfile(intent.getStringExtra(SipManager.EXTRA_LOCAL_URI));
} else {
if (VERBOSE) log("onReceive, action not processed: " + action);
}
diff --git a/sip/src/com/android/services/telephony/sip/SipConnection.java b/sip/src/com/android/services/telephony/sip/SipConnection.java
index 9165c47..bb316e2 100644
--- a/sip/src/com/android/services/telephony/sip/SipConnection.java
+++ b/sip/src/com/android/services/telephony/sip/SipConnection.java
@@ -225,6 +225,8 @@
case DIALING:
case ALERTING:
setDialing();
+ // For SIP calls, we need to ask the framework to play the ringback for us.
+ setRequestingRingback(true);
break;
case INCOMING:
case WAITING:
diff --git a/sip/src/com/android/services/telephony/sip/SipConnectionService.java b/sip/src/com/android/services/telephony/sip/SipConnectionService.java
index b12709b..16efc4d 100644
--- a/sip/src/com/android/services/telephony/sip/SipConnectionService.java
+++ b/sip/src/com/android/services/telephony/sip/SipConnectionService.java
@@ -32,7 +32,7 @@
import android.telecomm.ConnectionRequest;
import android.telecomm.ConnectionService;
import android.telecomm.PhoneAccountHandle;
-import android.telecomm.PropertyPresentation;
+import android.telecomm.TelecommManager;
import android.telephony.DisconnectCause;
import android.util.Log;
@@ -61,12 +61,6 @@
super.onCreate();
}
- static PhoneAccountHandle getPhoneAccountHandle(Context context) {
- return new PhoneAccountHandle(
- new ComponentName(context, SipConnectionService.class),
- null /* id */);
- }
-
@Override
public Connection onCreateOutgoingConnection(
PhoneAccountHandle connectionManagerAccount,
@@ -86,9 +80,8 @@
DisconnectCause.OUTGOING_FAILURE, "Did not match service connection");
}
-
final SipConnection connection = new SipConnection();
- connection.setHandle(request.getAddress(), PropertyPresentation.ALLOWED);
+ connection.setHandle(request.getAddress(), TelecommManager.PRESENTATION_ALLOWED);
connection.setInitializing();
connection.onAddedToCallService();
boolean attemptCall = true;
diff --git a/sip/src/com/android/services/telephony/sip/SipEditor.java b/sip/src/com/android/services/telephony/sip/SipEditor.java
index b35f28c..fbf3bd1 100644
--- a/sip/src/com/android/services/telephony/sip/SipEditor.java
+++ b/sip/src/com/android/services/telephony/sip/SipEditor.java
@@ -16,11 +16,6 @@
package com.android.services.telephony.sip;
-import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneConstants;
-import com.android.services.telephony.sip.SipUtil;
-
-import android.app.ActionBar;
import android.app.AlertDialog;
import android.content.Intent;
import android.net.sip.SipManager;
@@ -38,7 +33,6 @@
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
-import android.view.View;
import android.widget.Button;
import android.widget.Toast;
@@ -63,18 +57,16 @@
private static final char SCRAMBLED = '*';
private static final int NA = 0;
- private PrimaryAccountSelector mPrimaryAccountSelector;
private AdvancedSettings mAdvancedSettings;
private SipSharedPreferences mSharedPreferences;
private boolean mDisplayNameSet;
private boolean mHomeButtonClicked;
private boolean mUpdateRequired;
- private boolean mUpdatedFieldIsEmpty;
- private SipManager mSipManager;
private SipProfileDb mProfileDb;
private SipProfile mOldProfile;
private Button mRemoveButton;
+ private SipAccountRegistry mSipAccountRegistry;
enum PreferenceKey {
Username(R.string.username, 0, R.string.default_preference_summary),
@@ -159,9 +151,9 @@
if (VERBOSE) log("onCreate, start profile editor");
super.onCreate(savedInstanceState);
- mSipManager = SipManager.newInstance(this);
mSharedPreferences = new SipSharedPreferences(this);
mProfileDb = new SipProfileDb(this);
+ mSipAccountRegistry = SipAccountRegistry.getInstance();
setContentView(R.layout.sip_settings_ui);
addPreferencesFromResource(R.xml.sip_edit);
@@ -180,7 +172,6 @@
}
mAdvancedSettings = new AdvancedSettings();
- mPrimaryAccountSelector = new PrimaryAccountSelector(p);
loadPreferencesFromProfile(p);
}
@@ -244,32 +235,29 @@
return super.onKeyDown(keyCode, event);
}
+ /**
+ * Saves a {@link SipProfile} and registers the associated
+ * {@link android.telecomm.PhoneAccount}.
+ *
+ * @param p The {@link SipProfile} to register.
+ * @throws IOException Exception resulting from profile save.
+ */
private void saveAndRegisterProfile(SipProfile p) throws IOException {
if (p == null) return;
mProfileDb.saveProfile(p);
- if (p.getAutoRegistration() || mSharedPreferences.isPrimaryAccount(p.getUriString())) {
- try {
- mSipManager.open(
- p, SipUtil.createIncomingCallPendingIntent(this, p.getUriString()), null);
- } catch (Exception e) {
- log("saveAndRegisterProfile, register failed for profile: " + p.getUriString() +
- ", exception: " + e);
- }
- }
+ mSipAccountRegistry.startSipService(this, p.getUriString());
}
+ /**
+ * Deletes a {@link SipProfile} and un-registers the associated
+ * {@link android.telecomm.PhoneAccount}.
+ *
+ * @param p The {@link SipProfile} to delete.
+ */
private void deleteAndUnregisterProfile(SipProfile p) {
if (p == null) return;
mProfileDb.deleteProfile(p);
- unregisterProfile(p.getUriString());
- }
-
- private void unregisterProfile(String uri) {
- try {
- mSipManager.close(uri);
- } catch (Exception e) {
- log("unregisterProfile, unregister failed for profile: " + uri + ", exception: " + e);
- }
+ mSipAccountRegistry.stopSipService(this, p.getUriString());
}
private void setRemovedProfileAndFinish() {
@@ -371,15 +359,6 @@
}
}
- private void unregisterOldPrimaryAccount() {
- String primaryAccountUri = mSharedPreferences.getPrimaryAccount();
- if (VERBOSE) log("unregisterOldPrimaryAccount, old primary: " + primaryAccountUri);
- if ((primaryAccountUri != null) && !mSharedPreferences.isReceivingCallsEnabled()) {
- if (VERBOSE) log("unregisterOldPrimaryAccount, calling unregister");
- unregisterProfile(primaryAccountUri);
- }
- }
-
private void replaceProfile(final SipProfile oldProfile, final SipProfile newProfile) {
// Replace profile in a background thread as it takes time to access the
// storage; do finish() once everything goes fine.
@@ -388,12 +367,6 @@
new Thread(new Runnable() {
public void run() {
try {
- // if new profile is primary, unregister the old primary account
- if ((newProfile != null) && mPrimaryAccountSelector.isSelected()) {
- unregisterOldPrimaryAccount();
- }
-
- mPrimaryAccountSelector.commit(newProfile);
deleteAndUnregisterProfile(oldProfile);
saveAndRegisterProfile(newProfile);
finish();
@@ -430,10 +403,8 @@
public boolean onPreferenceChange(Preference pref, Object newValue) {
if (!mUpdateRequired) {
mUpdateRequired = true;
- if (mOldProfile != null) {
- unregisterProfile(mOldProfile.getUriString());
- }
}
+
if (pref instanceof CheckBoxPreference) {
invalidateOptionsMenu();
return true;
@@ -547,47 +518,6 @@
return new String(cc);
}
- // only takes care of the primary account setting in SipSharedSettings
- private class PrimaryAccountSelector {
- private CheckBoxPreference mCheckbox;
- private final boolean mWasPrimaryAccount;
-
- // @param profile profile to be edited; null if adding new profile
- PrimaryAccountSelector(SipProfile profile) {
- mCheckbox = (CheckBoxPreference) getPreferenceScreen()
- .findPreference(getString(R.string.set_primary));
- boolean noPrimaryAccountSet = !mSharedPreferences.hasPrimaryAccount();
- boolean editNewProfile = (profile == null);
- mWasPrimaryAccount = !editNewProfile && mSharedPreferences.isPrimaryAccount(
- profile.getUriString());
-
- if (VERBOSE) {
- log(" noPrimaryAccountSet: " + noPrimaryAccountSet);
- log(" editNewProfile: " + editNewProfile);
- log(" mWasPrimaryAccount: " + mWasPrimaryAccount);
- }
-
- mCheckbox.setChecked(mWasPrimaryAccount || (editNewProfile && noPrimaryAccountSet));
- }
-
- boolean isSelected() {
- return mCheckbox.isChecked();
- }
-
- // profile is null if the user removes it
- void commit(SipProfile profile) {
- if ((profile != null) && mCheckbox.isChecked()) {
- mSharedPreferences.setPrimaryAccount(profile.getUriString());
- } else if (mWasPrimaryAccount) {
- mSharedPreferences.unsetPrimaryAccount();
- }
- if (VERBOSE) {
- log("PrimaryAccountSelector.commit, new primary account: " +
- mSharedPreferences.getPrimaryAccount());
- }
- }
- }
-
private class AdvancedSettings implements Preference.OnPreferenceClickListener {
private Preference mAdvancedSettingsTrigger;
private Preference[] mPreferences;
diff --git a/sip/src/com/android/services/telephony/sip/SipSettings.java b/sip/src/com/android/services/telephony/sip/SipSettings.java
index f6e6101..1dca310 100644
--- a/sip/src/com/android/services/telephony/sip/SipSettings.java
+++ b/sip/src/com/android/services/telephony/sip/SipSettings.java
@@ -39,6 +39,8 @@
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceActivity;
import android.preference.PreferenceCategory;
+import android.telecomm.PhoneAccount;
+import android.telecomm.TelecommManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
@@ -104,13 +106,9 @@
void updateSummary(String registrationStatus) {
int profileUid = mProfile.getCallingUid();
- boolean isPrimary = mProfile.getUriString().equals(
- mSipSharedPreferences.getPrimaryAccount());
if (VERBOSE) {
log("SipPreference.updateSummary, profile uid: " + profileUid +
- " isPrimary: " + isPrimary +
" registration: " + registrationStatus +
- " Primary: " + mSipSharedPreferences.getPrimaryAccount() +
" status: " + registrationStatus);
}
String summary = "";
@@ -118,9 +116,6 @@
// from third party apps
summary = getString(R.string.third_party_account_summary,
getPackageNameFromUid(profileUid));
- } else if (isPrimary) {
- summary = getString(R.string.primary_account_summary_with,
- registrationStatus);
} else {
summary = registrationStatus;
}
@@ -219,36 +214,35 @@
});
}
- private synchronized void handleSipReceiveCallsOption(boolean enabled) {
- mSipSharedPreferences.setReceivingCallsEnabled(enabled);
+ /**
+ * Handles changes to the "receive calls" option.
+ *
+ * @param isReceivingCalls {@code True} if receiving incoming SIP calls.
+ */
+ private synchronized void handleSipReceiveCallsOption(boolean isReceivingCalls) {
+ mSipSharedPreferences.setReceivingCallsEnabled(isReceivingCalls);
+
+ // Mark all profiles as auto-register if we are now receiving calls.
List<SipProfile> sipProfileList = mProfileDb.retrieveSipProfileList();
for (SipProfile p : sipProfileList) {
- String sipUri = p.getUriString();
- p = updateAutoRegistrationFlag(p, enabled);
- try {
- if (enabled) {
- mSipManager.open(
- p, SipUtil.createIncomingCallPendingIntent(this, sipUri), null);
- } else {
- mSipManager.close(sipUri);
- if (mSipSharedPreferences.isPrimaryAccount(sipUri)) {
- // re-open in order to make calls
- mSipManager.open(p);
- }
- }
- } catch (Exception e) {
- log("handleSipReceiveCallsOption, register failed: " + e);
- }
+ p = updateAutoRegistrationFlag(p, isReceivingCalls);
}
+
+ // Restart all Sip services to ensure we reflect whether we are receiving calls.
+ SipAccountRegistry sipAccountRegistry = SipAccountRegistry.getInstance();
+ sipAccountRegistry.restartSipService(this);
+
updateProfilesStatus();
}
- private SipProfile updateAutoRegistrationFlag(
- SipProfile p, boolean enabled) {
+ private SipProfile updateAutoRegistrationFlag(SipProfile p, boolean enabled) {
SipProfile newProfile = new SipProfile.Builder(p)
.setAutoRegistration(enabled)
.build();
try {
+ // Note: The profile is updated, but the associated PhoneAccount is left alone since
+ // the only thing that changed is the auto-registration flag, which is not part of the
+ // PhoneAccount.
mProfileDb.deleteProfile(p);
mProfileDb.saveProfile(newProfile);
} catch (Exception e) {
diff --git a/sip/src/com/android/services/telephony/sip/SipSharedPreferences.java b/sip/src/com/android/services/telephony/sip/SipSharedPreferences.java
index b5d1fc2..bad7dd5 100644
--- a/sip/src/com/android/services/telephony/sip/SipSharedPreferences.java
+++ b/sip/src/com/android/services/telephony/sip/SipSharedPreferences.java
@@ -16,14 +16,12 @@
package com.android.services.telephony.sip;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.sip.SipManager;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
-import android.text.TextUtils;
import android.util.Log;
/**
@@ -34,7 +32,13 @@
private static final boolean VERBOSE = false; /* STOP SHIP if true */
private static final String SIP_SHARED_PREFERENCES = "SIP_PREFERENCES";
+
+ /**
+ * @deprecated Primary account selection for SIP accounts is no longer relevant.
+ */
+ @Deprecated
private static final String KEY_PRIMARY_ACCOUNT = "primary";
+
private static final String KEY_NUMBER_OF_PROFILES = "profiles";
private SharedPreferences mPreferences;
@@ -46,31 +50,15 @@
mContext = context;
}
- public void setPrimaryAccount(String accountUri) {
- SharedPreferences.Editor editor = mPreferences.edit();
- editor.putString(KEY_PRIMARY_ACCOUNT, accountUri);
- editor.apply();
- }
-
- public void unsetPrimaryAccount() {
- setPrimaryAccount(null);
- }
-
- /** Returns the primary account URI or null if it does not exist. */
+ /**
+ * Returns the primary account URI or null if it does not exist.
+ * @deprecated The primary account setting is no longer used.
+ */
+ @Deprecated
public String getPrimaryAccount() {
return mPreferences.getString(KEY_PRIMARY_ACCOUNT, null);
}
- public boolean isPrimaryAccount(String accountUri) {
- return accountUri.equals(
- mPreferences.getString(KEY_PRIMARY_ACCOUNT, null));
- }
-
- public boolean hasPrimaryAccount() {
- return !TextUtils.isEmpty(
- mPreferences.getString(KEY_PRIMARY_ACCOUNT, null));
- }
-
public void setProfilesCount(int number) {
SharedPreferences.Editor editor = mPreferences.edit();
editor.putInt(KEY_NUMBER_OF_PROFILES, number);
@@ -114,6 +102,18 @@
}
}
+ /**
+ * Performs cleanup of the shared preferences, removing the deprecated primary account key if
+ * it exists.
+ */
+ public void cleanupPrimaryAccountSetting() {
+ if (mPreferences.contains(KEY_PRIMARY_ACCOUNT)) {
+ SharedPreferences.Editor editor = mPreferences.edit();
+ editor.remove(KEY_PRIMARY_ACCOUNT);
+ editor.apply();
+ }
+ }
+
// TODO: back up to Android Backup
private static void log(String msg) {
diff --git a/sip/src/com/android/services/telephony/sip/SipUtil.java b/sip/src/com/android/services/telephony/sip/SipUtil.java
index e926fa1..340ebda 100644
--- a/sip/src/com/android/services/telephony/sip/SipUtil.java
+++ b/sip/src/com/android/services/telephony/sip/SipUtil.java
@@ -16,14 +16,23 @@
package com.android.services.telephony.sip;
+import com.android.phone.R;
+
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.net.Uri;
import android.net.sip.SipManager;
+import android.net.sip.SipProfile;
+import android.provider.Settings;
+import android.telecomm.PhoneAccount;
import android.telecomm.PhoneAccountHandle;
import android.telecomm.TelecommManager;
+import java.util.Arrays;
+import java.util.List;
+
public class SipUtil {
static final String LOG_TAG = "SIP";
static final String EXTRA_INCOMING_CALL_INTENT =
@@ -33,21 +42,15 @@
static final String GATEWAY_PROVIDER_PACKAGE =
"com.android.phone.extra.GATEWAY_PROVIDER_PACKAGE";
- private static boolean sIsVoipSupported;
- private static boolean sIsVoipSupportedInitialized;
-
private SipUtil() {
}
public static boolean isVoipSupported(Context context) {
- if (!sIsVoipSupportedInitialized) {
- sIsVoipSupported = SipManager.isVoipSupported(context) &&
- context.getResources().getBoolean(
- com.android.internal.R.bool.config_built_in_sip_phone) &&
- context.getResources().getBoolean(
- com.android.internal.R.bool.config_voice_capable);
- }
- return sIsVoipSupported;
+ return SipManager.isVoipSupported(context) &&
+ context.getResources().getBoolean(
+ com.android.internal.R.bool.config_built_in_sip_phone) &&
+ context.getResources().getBoolean(
+ com.android.internal.R.bool.config_voice_capable);
}
static PendingIntent createIncomingCallPendingIntent(
@@ -74,4 +77,55 @@
return new PhoneAccountHandle(
new ComponentName(context, SipConnectionService.class), sipUri);
}
+
+ /**
+ * Determines if the {@link android.telecomm.PhoneAccount} associated with a {@link SipProfile}
+ * is enabled.
+ *
+ * @param context The {@link Context}.
+ * @param profile The {@link SipProfile}.
+ * @return {@code True} if the {@code PhoneAccount} is enabled.
+ */
+ static boolean isPhoneAccountEnabled(Context context, SipProfile profile) {
+ PhoneAccount phoneAccount = TelecommManager.from(context)
+ .getPhoneAccount(SipUtil.createAccountHandle(context, profile.getUriString()));
+ return phoneAccount != null && phoneAccount.isEnabled();
+ }
+
+ /**
+ * Creates a PhoneAccount for a SipProfile.
+ *
+ * @param context The context
+ * @param profile The SipProfile.
+ * @return The PhoneAccount.
+ */
+ static PhoneAccount createPhoneAccount(Context context, SipProfile profile) {
+
+ PhoneAccountHandle accountHandle =
+ SipUtil.createAccountHandle(context, profile.getUriString());
+
+ List supportedUriSchemes = Arrays.asList(PhoneAccount.SCHEME_SIP);
+ if (useSipForPstnCalls(context)) {
+ supportedUriSchemes.add(PhoneAccount.SCHEME_TEL);
+ }
+
+ PhoneAccount.Builder builder = PhoneAccount.builder(accountHandle, profile.getDisplayName())
+ .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
+ .setAddress(Uri.parse(profile.getUriString()))
+ .setShortDescription(profile.getDisplayName())
+ .setIconResId(R.drawable.ic_dialer_sip_black_24dp)
+ .setSupportedUriSchemes(supportedUriSchemes);
+
+ return builder.build();
+ }
+
+ /**
+ * Determines if the user has chosen to use SIP for PSTN calls as well as SIP calls.
+ * @param context The context.
+ * @return {@code True} if SIP should be used for PSTN calls.
+ */
+ private static boolean useSipForPstnCalls(Context context) {
+ final SipSharedPreferences sipSharedPreferences = new SipSharedPreferences(context);
+ return sipSharedPreferences.getSipCallOption().equals(Settings.System.SIP_ALWAYS);
+ }
}
diff --git a/src/com/android/phone/CallFeaturesSetting.java b/src/com/android/phone/CallFeaturesSetting.java
index 88de152..bb23292 100644
--- a/src/com/android/phone/CallFeaturesSetting.java
+++ b/src/com/android/phone/CallFeaturesSetting.java
@@ -465,6 +465,11 @@
*/
private boolean mReadingSettingsForDefaultProvider = false;
+ /**
+ * Used to indicate that the voicemail preference should be shown.
+ */
+ private boolean mShowVoicemailPreference = false;
+
/*
* Click Listeners, handle click based on objects attached to UI.
*/
@@ -603,6 +608,22 @@
return false;
}
+ /**
+ * Called just prior to showing an AccountSelection dialog to re-populate the model of the
+ * AccountSelection dialog. Important to ensure changes to the enabled state of
+ * {@code PhoneAccount}s are reflected in the dialog.
+ *
+ * @param pref The account selection preference dialog being shown.
+ */
+ @Override
+ public void onAccountSelectionDialogShow(AccountSelectionPreference pref) {
+ if (pref == mDefaultOutgoingAccount) {
+ populateDefaultOutgoingAccountsModel();
+ } else if (pref == mSimCallManagerAccount) {
+ populateSimCallManagerAccountsModel();
+ }
+ }
+
@Override
public void onDialogClosed(EditPhoneNumberPreference preference, int buttonClicked) {
if (DBG) log("onPreferenceClick: request preference click on dialog close: " +
@@ -1509,13 +1530,121 @@
super.onCreate(icicle);
if (DBG) log("onCreate(). Intent: " + getIntent());
mPhone = PhoneGlobals.getPhone();
+ mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
+
+ // create intent to bring up contact list
+ mContactListIntent = new Intent(Intent.ACTION_GET_CONTENT);
+ mContactListIntent.setType(android.provider.Contacts.Phones.CONTENT_ITEM_TYPE);
+
+ mVoicemailRingtoneLookupRunnable = new Runnable() {
+ @Override
+ public void run() {
+ if (mVoicemailNotificationRingtone != null) {
+ SettingsUtil.updateRingtoneName(
+ mPhone.getContext(),
+ mVoicemailRingtoneLookupComplete,
+ RingtoneManager.TYPE_NOTIFICATION,
+ mVoicemailNotificationRingtone,
+ MSG_UPDATE_VOICEMAIL_RINGTONE_SUMMARY);
+ }
+ }
+ };
+
+ ActionBar actionBar = getActionBar();
+ if (actionBar != null) {
+ // android.R.id.home will be triggered in onOptionsItemSelected()
+ actionBar.setDisplayShowHomeEnabled(true);
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowTitleEnabled(true);
+ }
+
+ // Show the voicemail preference in onResume if the calling intent specifies the
+ // ACTION_ADD_VOICEMAIL action.
+ mShowVoicemailPreference = (icicle == null) &&
+ getIntent().getAction().equals(ACTION_ADD_VOICEMAIL);
+ }
+
+ private void initPhoneAccountPreferences() {
+ mDefaultOutgoingAccount = (AccountSelectionPreference)
+ findPreference(DEFAULT_OUTGOING_ACCOUNT_KEY);
+ mSimCallManagerAccount = (AccountSelectionPreference)
+ findPreference(WIFI_CALL_MANAGER_ACCOUNT_KEY);
+
+ TelecommManager telecommManager = TelecommManager.from(this);
+
+ int allPhoneAccountsCount = telecommManager.getAllPhoneAccountsCount();
+ // Show the phone accounts preference if there are is more than one phone account (this
+ // includes disabled phone accounts). The default selection, however, only includes those
+ // PhoneAccounts which are enabled.
+ if (allPhoneAccountsCount > 1) {
+ populateDefaultOutgoingAccountsModel();
+
+ mDefaultOutgoingAccount.setListener(this);
+ } else {
+ getPreferenceScreen().removePreference(mDefaultOutgoingAccount);
+ }
+
+ List<PhoneAccountHandle> simCallManagers = telecommManager.getSimCallManagers();
+ if (!simCallManagers.isEmpty()) {
+ populateSimCallManagerAccountsModel();
+ mSimCallManagerAccount.setListener(this);
+ } else {
+ getPreferenceScreen().removePreference(mSimCallManagerAccount);
+ }
+ }
+
+ private void createSipCallSettings() {
+ // Add Internet call settings.
+ if (SipUtil.isVoipSupported(this)) {
+ mSipManager = SipManager.newInstance(this);
+ mSipSharedPreferences = new SipSharedPreferences(this);
+ addPreferencesFromResource(
+ com.android.services.telephony.sip.R.xml.sip_settings_category);
+ mButtonSipCallOptions = getSipCallOptionPreference();
+ mButtonSipCallOptions.setOnPreferenceChangeListener(this);
+ mButtonSipCallOptions.setValueIndex(
+ mButtonSipCallOptions.findIndexOfValue(
+ mSipSharedPreferences.getSipCallOption()));
+ mButtonSipCallOptions.setSummary(mButtonSipCallOptions.getEntry());
+ }
+ }
+
+ private boolean canLaunchIntent(Intent intent) {
+ PackageManager pm = getPackageManager();
+ return pm.resolveActivity(intent, PackageManager.GET_ACTIVITIES) != null;
+ }
+
+ // Gets the call options for SIP depending on whether SIP is allowed only
+ // on Wi-Fi only; also make the other options preference invisible.
+ private ListPreference getSipCallOptionPreference() {
+ ListPreference wifiAnd3G = (ListPreference)
+ findPreference(BUTTON_SIP_CALL_OPTIONS);
+ ListPreference wifiOnly = (ListPreference)
+ findPreference(BUTTON_SIP_CALL_OPTIONS_WIFI_ONLY);
+ PreferenceScreen sipSettings = (PreferenceScreen)
+ getPreferenceScreen().findPreference(SIP_SETTINGS_PREFERENCE_SCREEN_KEY);
+ if (SipManager.isSipWifiOnly(this)) {
+ sipSettings.removePreference(wifiAnd3G);
+ return wifiOnly;
+ } else {
+ sipSettings.removePreference(wifiOnly);
+ return wifiAnd3G;
+ }
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mForeground = true;
+
+ PreferenceScreen preferenceScreen = getPreferenceScreen();
+ if (preferenceScreen != null) {
+ preferenceScreen.removeAll();
+ }
addPreferencesFromResource(R.xml.call_feature_setting);
-
initPhoneAccountPreferences();
- mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
-
// get buttons
PreferenceScreen prefSet = getPreferenceScreen();
mSubMenuVoicemailSettings = (EditPhoneNumberPreference)findPreference(BUTTON_VOICEMAIL_KEY);
@@ -1541,7 +1670,6 @@
initVoiceMailProviders();
}
- final ContentResolver contentResolver = getContentResolver();
if (mButtonDTMF != null) {
if (getResources().getBoolean(R.bool.dtmf_type_enabled)) {
@@ -1609,134 +1737,29 @@
}
}
- // create intent to bring up contact list
- mContactListIntent = new Intent(Intent.ACTION_GET_CONTENT);
- mContactListIntent.setType(android.provider.Contacts.Phones.CONTENT_ITEM_TYPE);
-
// check the intent that started this activity and pop up the voicemail
// dialog if we've been asked to.
// If we have at least one non default VM provider registered then bring up
// the selection for the VM provider, otherwise bring up a VM number dialog.
// We only bring up the dialog the first time we are called (not after orientation change)
- if (icicle == null) {
- if (getIntent().getAction().equals(ACTION_ADD_VOICEMAIL) &&
- mVoicemailProviders != null) {
- if (DBG) {
- log("ACTION_ADD_VOICEMAIL Intent is thrown. current VM data size: "
- + mVMProvidersData.size());
- }
- if (mVMProvidersData.size() > 1) {
- simulatePreferenceClick(mVoicemailProviders);
- } else {
- onPreferenceChange(mVoicemailProviders, DEFAULT_VM_PROVIDER_KEY);
- mVoicemailProviders.setValue(DEFAULT_VM_PROVIDER_KEY);
- }
+ if (mShowVoicemailPreference && mVoicemailProviders != null) {
+ if (DBG) {
+ log("ACTION_ADD_VOICEMAIL Intent is thrown. current VM data size: "
+ + mVMProvidersData.size());
}
+ if (mVMProvidersData.size() > 1) {
+ simulatePreferenceClick(mVoicemailProviders);
+ } else {
+ onPreferenceChange(mVoicemailProviders, DEFAULT_VM_PROVIDER_KEY);
+ mVoicemailProviders.setValue(DEFAULT_VM_PROVIDER_KEY);
+ }
+ mShowVoicemailPreference = false;
}
+
updateVoiceNumberField();
mVMProviderSettingsForced = false;
createSipCallSettings();
- mVoicemailRingtoneLookupRunnable = new Runnable() {
- @Override
- public void run() {
- if (mVoicemailNotificationRingtone != null) {
- SettingsUtil.updateRingtoneName(
- mPhone.getContext(),
- mVoicemailRingtoneLookupComplete,
- RingtoneManager.TYPE_NOTIFICATION,
- mVoicemailNotificationRingtone,
- MSG_UPDATE_VOICEMAIL_RINGTONE_SUMMARY);
- }
- }
- };
-
- ActionBar actionBar = getActionBar();
- if (actionBar != null) {
- // android.R.id.home will be triggered in onOptionsItemSelected()
- actionBar.setDisplayShowHomeEnabled(true);
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowTitleEnabled(true);
- }
- }
-
- private void initPhoneAccountPreferences() {
- mDefaultOutgoingAccount = (AccountSelectionPreference)
- findPreference(DEFAULT_OUTGOING_ACCOUNT_KEY);
- mSimCallManagerAccount = (AccountSelectionPreference)
- findPreference(WIFI_CALL_MANAGER_ACCOUNT_KEY);
-
- TelecommManager telecommManager = TelecommManager.from(this);
-
- List<PhoneAccountHandle> enabledPhoneAccounts = telecommManager.getEnabledPhoneAccounts();
- if (enabledPhoneAccounts.size() > 1) {
- mDefaultOutgoingAccount.setModel(
- telecommManager,
- enabledPhoneAccounts,
- telecommManager.getUserSelectedOutgoingPhoneAccount(),
- getString(R.string.phone_accounts_ask_every_time));
- mDefaultOutgoingAccount.setListener(this);
- } else {
- getPreferenceScreen().removePreference(mDefaultOutgoingAccount);
- }
-
- List<PhoneAccountHandle> simCallManagers = telecommManager.getSimCallManagers();
- if (!simCallManagers.isEmpty()) {
- mSimCallManagerAccount.setModel(
- telecommManager,
- simCallManagers,
- telecommManager.getSimCallManager(),
- getString(R.string.wifi_calling_do_not_use));
- mSimCallManagerAccount.setListener(this);
- } else {
- getPreferenceScreen().removePreference(mSimCallManagerAccount);
- }
- }
-
- private void createSipCallSettings() {
- // Add Internet call settings.
- if (SipUtil.isVoipSupported(this)) {
- mSipManager = SipManager.newInstance(this);
- mSipSharedPreferences = new SipSharedPreferences(this);
- addPreferencesFromResource(
- com.android.services.telephony.sip.R.xml.sip_settings_category);
- mButtonSipCallOptions = getSipCallOptionPreference();
- mButtonSipCallOptions.setOnPreferenceChangeListener(this);
- mButtonSipCallOptions.setValueIndex(
- mButtonSipCallOptions.findIndexOfValue(
- mSipSharedPreferences.getSipCallOption()));
- mButtonSipCallOptions.setSummary(mButtonSipCallOptions.getEntry());
- }
- }
-
- private boolean canLaunchIntent(Intent intent) {
- PackageManager pm = getPackageManager();
- return pm.resolveActivity(intent, PackageManager.GET_ACTIVITIES) != null;
- }
-
- // Gets the call options for SIP depending on whether SIP is allowed only
- // on Wi-Fi only; also make the other options preference invisible.
- private ListPreference getSipCallOptionPreference() {
- ListPreference wifiAnd3G = (ListPreference)
- findPreference(BUTTON_SIP_CALL_OPTIONS);
- ListPreference wifiOnly = (ListPreference)
- findPreference(BUTTON_SIP_CALL_OPTIONS_WIFI_ONLY);
- PreferenceScreen sipSettings = (PreferenceScreen)
- getPreferenceScreen().findPreference(SIP_SETTINGS_PREFERENCE_SCREEN_KEY);
- if (SipManager.isSipWifiOnly(this)) {
- sipSettings.removePreference(wifiAnd3G);
- return wifiOnly;
- } else {
- sipSettings.removePreference(wifiOnly);
- return wifiAnd3G;
- }
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- mForeground = true;
-
if (isAirplaneModeOn()) {
Preference sipSettings = findPreference(SIP_SETTINGS_PREFERENCE_SCREEN_KEY);
PreferenceScreen screen = getPreferenceScreen();
@@ -2117,6 +2140,41 @@
}
/**
+ * Populates the phone accounts which could potentially be selected as the default.
+ */
+ private void populateDefaultOutgoingAccountsModel() {
+ if (mDefaultOutgoingAccount == null ) {
+ return;
+ }
+
+ TelecommManager telecommManager = TelecommManager.from(this);
+ List<PhoneAccountHandle> enabledPhoneAccounts = telecommManager.getEnabledPhoneAccounts();
+ mDefaultOutgoingAccount.setModel(
+ telecommManager,
+ enabledPhoneAccounts,
+ telecommManager.getUserSelectedOutgoingPhoneAccount(),
+ getString(R.string.phone_accounts_ask_every_time));
+ }
+
+ /**
+ * Populates the phone accounts which could potentially be selected as the default sim call
+ * manager.
+ */
+ private void populateSimCallManagerAccountsModel() {
+ if (mSimCallManagerAccount == null) {
+ return;
+ }
+
+ TelecommManager telecommManager = TelecommManager.from(this);
+ List<PhoneAccountHandle> simCallManagers = telecommManager.getSimCallManagers();
+ mSimCallManagerAccount.setModel(
+ telecommManager,
+ simCallManagers,
+ telecommManager.getSimCallManager(),
+ getString(R.string.wifi_calling_do_not_use));
+ }
+
+ /**
* Deletes settings for the specified provider.
*/
private void deleteSettingsForVoicemailProvider(String key) {
diff --git a/src/com/android/phone/MobileNetworkSettings.java b/src/com/android/phone/MobileNetworkSettings.java
index e6fc11c..20134ba 100644
--- a/src/com/android/phone/MobileNetworkSettings.java
+++ b/src/com/android/phone/MobileNetworkSettings.java
@@ -122,10 +122,7 @@
@Override
public void onDismiss(DialogInterface dialog) {
// Assuming that onClick gets called first
- if (!mOkClicked) {
- mButtonDataRoam.setChecked(false);
- getPreferenceScreen().setEnabled(true);
- }
+ mButtonDataRoam.setChecked(mOkClicked);
}
/**
@@ -185,6 +182,9 @@
preferredNetworkMode);
mButtonEnabledNetworks.setValue(Integer.toString(settingsNetworkMode));
return true;
+ } else if (preference == mButtonDataRoam) {
+ // Do not disable the preference screen if the user clicks Data roaming.
+ return true;
} else {
// if the button is anything but the simple toggle preference,
// we'll need to disable all preferences to reject all click
@@ -249,7 +249,7 @@
boolean isLteOnCdma = mPhone.getLteOnCdmaMode() == PhoneConstants.LTE_ON_CDMA_TRUE;
mIsGlobalCdma = isLteOnCdma && getResources().getBoolean(R.bool.config_show_cdma);
TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
- if (tm.getSimplifiedNetworkSettingsEnabled(SubscriptionManager.getDefaultSubId())) {
+ if (tm.getSimplifiedNetworkSettingsEnabledForSubscriber(SubscriptionManager.getDefaultSubId())) {
prefSet.removePreference(mButtonPreferredNetworkMode);
prefSet.removePreference(mButtonEnabledNetworks);
prefSet.removePreference(mLteDataServicePref);
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 99cb206..2ac98d3 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -21,6 +21,7 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
@@ -37,6 +38,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
+import android.preference.PreferenceManager;
import android.provider.Settings;
import android.telephony.CellInfo;
import android.telephony.IccOpenLogicalChannelResponse;
@@ -129,12 +131,11 @@
AppOpsManager mAppOps;
MainThreadHandler mMainThreadHandler;
- /**
- * Indicates if Android should display a simplified Mobile Network Settings UI in a specific
- * subscription.
- */
- Set<Long> mSimplifiedNetworkSettings;
- Map<Long, AdnRecord> mAdnRecordsForDisplay;
+ SharedPreferences carrierPrivilegeConfigs;
+ private static final String PREF_CARRIERS_ALPHATAG_PREFIX = "carrier_alphtag_";
+ private static final String PREF_CARRIERS_NUMBER_PREFIX = "carrier_number_";
+ private static final String PREF_CARRIERS_SIMPLIFIED_NETWORK_SETTINGS_PREFIX =
+ "carrier_simplified_network_settings_";
/**
* A request object to use for transmitting data to an ICC.
@@ -696,10 +697,10 @@
mApp = app;
mPhone = phone;
mCM = PhoneGlobals.getInstance().mCM;
- mSimplifiedNetworkSettings = new HashSet<Long>();
mAppOps = (AppOpsManager)app.getSystemService(Context.APP_OPS_SERVICE);
mMainThreadHandler = new MainThreadHandler();
- mAdnRecordsForDisplay = new HashMap<Long, AdnRecord>();
+ carrierPrivilegeConfigs =
+ PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
publish();
}
@@ -714,17 +715,17 @@
private Phone getPhone(long subId) {
// FIXME: hack for the moment
return mPhone;
- // return PhoneUtils.getPhoneUsingSubId(subId);
+ // return PhoneUtils.getPhoneForSubscriber(subId);
}
//
// Implementation of the ITelephony interface.
//
public void dial(String number) {
- dialUsingSubId(getPreferredVoiceSubscription(), number);
+ dialForSubscriber(getPreferredVoiceSubscription(), number);
}
- public void dialUsingSubId(long subId, String number) {
+ public void dialForSubscriber(long subId, String number) {
if (DBG) log("dial: " + number);
// No permission check needed here: This is just a wrapper around the
// ACTION_DIAL intent, which is available to any app since it puts up
@@ -746,10 +747,10 @@
}
public void call(String callingPackage, String number) {
- callUsingSubId(getPreferredVoiceSubscription(), callingPackage, number);
+ callForSubscriber(getPreferredVoiceSubscription(), callingPackage, number);
}
- public void callUsingSubId(long subId, String callingPackage, String number) {
+ public void callForSubscriber(long subId, String callingPackage, String number) {
if (DBG) log("call: " + number);
// This is just a wrapper around the ACTION_CALL intent, but we still
@@ -778,23 +779,23 @@
* @return true is a call was ended
*/
public boolean endCall() {
- return endCallUsingSubId(getDefaultSubscription());
+ return endCallForSubscriber(getDefaultSubscription());
}
/**
* End a call based on the call state of the subId
* @return true is a call was ended
*/
- public boolean endCallUsingSubId(long subId) {
+ public boolean endCallForSubscriber(long subId) {
enforceCallPermission();
return (Boolean) sendRequest(CMD_END_CALL, subId, null);
}
public void answerRingingCall() {
- answerRingingCallUsingSubId(getDefaultSubscription());
+ answerRingingCallForSubscriber(getDefaultSubscription());
}
- public void answerRingingCallUsingSubId(long subId) {
+ public void answerRingingCallForSubscriber(long subId) {
if (DBG) log("answerRingingCall...");
// TODO: there should eventually be a separate "ANSWER_PHONE" permission,
// but that can probably wait till the big TelephonyManager API overhaul.
@@ -865,26 +866,26 @@
}
public boolean isOffhook() {
- return isOffhookUsingSubId(getDefaultSubscription());
+ return isOffhookForSubscriber(getDefaultSubscription());
}
- public boolean isOffhookUsingSubId(long subId) {
+ public boolean isOffhookForSubscriber(long subId) {
return (getPhone(subId).getState() == PhoneConstants.State.OFFHOOK);
}
public boolean isRinging() {
- return (isRingingUsingSubId(getDefaultSubscription()));
+ return (isRingingForSubscriber(getDefaultSubscription()));
}
- public boolean isRingingUsingSubId(long subId) {
+ public boolean isRingingForSubscriber(long subId) {
return (getPhone(subId).getState() == PhoneConstants.State.RINGING);
}
public boolean isIdle() {
- return isIdleUsingSubId(getDefaultSubscription());
+ return isIdleForSubscriber(getDefaultSubscription());
}
- public boolean isIdleUsingSubId(long subId) {
+ public boolean isIdleForSubscriber(long subId) {
return (getPhone(subId).getState() == PhoneConstants.State.IDLE);
}
@@ -894,29 +895,29 @@
}
public boolean supplyPin(String pin) {
- return supplyPinUsingSubId(getDefaultSubscription(), pin);
+ return supplyPinForSubscriber(getDefaultSubscription(), pin);
}
- public boolean supplyPinUsingSubId(long subId, String pin) {
- int [] resultArray = supplyPinReportResultUsingSubId(subId, pin);
+ public boolean supplyPinForSubscriber(long subId, String pin) {
+ int [] resultArray = supplyPinReportResultForSubscriber(subId, pin);
return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
}
public boolean supplyPuk(String puk, String pin) {
- return supplyPukUsingSubId(getDefaultSubscription(), puk, pin);
+ return supplyPukForSubscriber(getDefaultSubscription(), puk, pin);
}
- public boolean supplyPukUsingSubId(long subId, String puk, String pin) {
- int [] resultArray = supplyPukReportResultUsingSubId(subId, puk, pin);
+ public boolean supplyPukForSubscriber(long subId, String puk, String pin) {
+ int [] resultArray = supplyPukReportResultForSubscriber(subId, puk, pin);
return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
}
/** {@hide} */
public int[] supplyPinReportResult(String pin) {
- return supplyPinReportResultUsingSubId(getDefaultSubscription(), pin);
+ return supplyPinReportResultForSubscriber(getDefaultSubscription(), pin);
}
- public int[] supplyPinReportResultUsingSubId(long subId, String pin) {
+ public int[] supplyPinReportResultForSubscriber(long subId, String pin) {
enforceModifyPermission();
final UnlockSim checkSimPin = new UnlockSim(getPhone(subId).getIccCard());
checkSimPin.start();
@@ -925,10 +926,10 @@
/** {@hide} */
public int[] supplyPukReportResult(String puk, String pin) {
- return supplyPukReportResultUsingSubId(getDefaultSubscription(), puk, pin);
+ return supplyPukReportResultForSubscriber(getDefaultSubscription(), puk, pin);
}
- public int[] supplyPukReportResultUsingSubId(long subId, String puk, String pin) {
+ public int[] supplyPukReportResultForSubscriber(long subId, String puk, String pin) {
enforceModifyPermission();
final UnlockSim checkSimPuk = new UnlockSim(getPhone(subId).getIccCard());
checkSimPuk.start();
@@ -1035,11 +1036,11 @@
}
public void updateServiceLocation() {
- updateServiceLocationUsingSubId(getDefaultSubscription());
+ updateServiceLocationForSubscriber(getDefaultSubscription());
}
- public void updateServiceLocationUsingSubId(long subId) {
+ public void updateServiceLocationForSubscriber(long subId) {
// No permission check needed here: this call is harmless, and it's
// needed for the ServiceState.requestStateUpdate() call (which is
// already intentionally exposed to 3rd parties.)
@@ -1047,32 +1048,32 @@
}
public boolean isRadioOn() {
- return isRadioOnUsingSubId(getDefaultSubscription());
+ return isRadioOnForSubscriber(getDefaultSubscription());
}
- public boolean isRadioOnUsingSubId(long subId) {
+ public boolean isRadioOnForSubscriber(long subId) {
return getPhone(subId).getServiceState().getState() != ServiceState.STATE_POWER_OFF;
}
public void toggleRadioOnOff() {
- toggleRadioOnOffUsingSubId(getDefaultSubscription());
+ toggleRadioOnOffForSubscriber(getDefaultSubscription());
}
- public void toggleRadioOnOffUsingSubId(long subId) {
+ public void toggleRadioOnOffForSubscriber(long subId) {
enforceModifyPermission();
- getPhone(subId).setRadioPower(!isRadioOnUsingSubId(subId));
+ getPhone(subId).setRadioPower(!isRadioOnForSubscriber(subId));
}
public boolean setRadio(boolean turnOn) {
- return setRadioUsingSubId(getDefaultSubscription(), turnOn);
+ return setRadioForSubscriber(getDefaultSubscription(), turnOn);
}
- public boolean setRadioUsingSubId(long subId, boolean turnOn) {
+ public boolean setRadioForSubscriber(long subId, boolean turnOn) {
enforceModifyPermission();
if ((getPhone(subId).getServiceState().getState() !=
ServiceState.STATE_POWER_OFF) != turnOn) {
- toggleRadioOnOffUsingSubId(subId);
+ toggleRadioOnOffForSubscriber(subId);
}
return true;
}
@@ -1106,10 +1107,10 @@
}
public boolean setRadioPower(boolean turnOn) {
- return setRadioPowerUsingSubId(getDefaultSubscription(), turnOn);
+ return setRadioPowerForSubscriber(getDefaultSubscription(), turnOn);
}
- public boolean setRadioPowerUsingSubId(long subId, boolean turnOn) {
+ public boolean setRadioPowerForSubscriber(long subId, boolean turnOn) {
enforceModifyPermission();
getPhone(subId).setRadioPower(turnOn);
return true;
@@ -1138,19 +1139,19 @@
}
public boolean handlePinMmi(String dialString) {
- return handlePinMmiUsingSubId(getDefaultSubscription(), dialString);
+ return handlePinMmiForSubscriber(getDefaultSubscription(), dialString);
}
- public boolean handlePinMmiUsingSubId(long subId, String dialString) {
+ public boolean handlePinMmiForSubscriber(long subId, String dialString) {
enforceModifyPermission();
return (Boolean) sendRequest(CMD_HANDLE_PIN_MMI, dialString, subId);
}
public int getCallState() {
- return getCallStateUsingSubId(getDefaultSubscription());
+ return getCallStateForSubscriber(getDefaultSubscription());
}
- public int getCallStateUsingSubId(long subId) {
+ public int getCallStateForSubscriber(long subId) {
return DefaultPhoneNotifier.convertCallState(getPhone(subId).getState());
}
@@ -1190,10 +1191,10 @@
@Override
public void enableLocationUpdates() {
- enableLocationUpdatesUsingSubId(getDefaultSubscription());
+ enableLocationUpdatesForSubscriber(getDefaultSubscription());
}
- public void enableLocationUpdatesUsingSubId(long subId) {
+ public void enableLocationUpdatesForSubscriber(long subId) {
mApp.enforceCallingOrSelfPermission(
android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
getPhone(subId).enableLocationUpdates();
@@ -1201,10 +1202,10 @@
@Override
public void disableLocationUpdates() {
- disableLocationUpdatesUsingSubId(getDefaultSubscription());
+ disableLocationUpdatesForSubscriber(getDefaultSubscription());
}
- public void disableLocationUpdatesUsingSubId(long subId) {
+ public void disableLocationUpdatesForSubscriber(long subId) {
mApp.enforceCallingOrSelfPermission(
android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
getPhone(subId).disableLocationUpdates();
@@ -1400,10 +1401,10 @@
}
public int getActivePhoneType() {
- return getActivePhoneTypeUsingSubId(getDefaultSubscription());
+ return getActivePhoneTypeForSubscriber(getDefaultSubscription());
}
- public int getActivePhoneTypeUsingSubId(long subId) {
+ public int getActivePhoneTypeForSubscriber(long subId) {
return getPhone(subId).getPhoneType();
}
@@ -1411,11 +1412,11 @@
* Returns the CDMA ERI icon index to display
*/
public int getCdmaEriIconIndex() {
- return getCdmaEriIconIndexUsingSubId(getDefaultSubscription());
+ return getCdmaEriIconIndexForSubscriber(getDefaultSubscription());
}
- public int getCdmaEriIconIndexUsingSubId(long subId) {
+ public int getCdmaEriIconIndexForSubscriber(long subId) {
return getPhone(subId).getCdmaEriIconIndex();
}
@@ -1425,10 +1426,10 @@
* 1 - FLASHING
*/
public int getCdmaEriIconMode() {
- return getCdmaEriIconModeUsingSubId(getDefaultSubscription());
+ return getCdmaEriIconModeForSubscriber(getDefaultSubscription());
}
- public int getCdmaEriIconModeUsingSubId(long subId) {
+ public int getCdmaEriIconModeForSubscriber(long subId) {
return getPhone(subId).getCdmaEriIconMode();
}
@@ -1436,10 +1437,10 @@
* Returns the CDMA ERI text,
*/
public String getCdmaEriText() {
- return getCdmaEriTextUsingSubId(getDefaultSubscription());
+ return getCdmaEriTextForSubscriber(getDefaultSubscription());
}
- public String getCdmaEriTextUsingSubId(long subId) {
+ public String getCdmaEriTextForSubscriber(long subId) {
return getPhone(subId).getCdmaEriText();
}
@@ -1478,13 +1479,13 @@
* Returns the unread count of voicemails
*/
public int getVoiceMessageCount() {
- return getVoiceMessageCountUsingSubId(getDefaultSubscription());
+ return getVoiceMessageCountForSubscriber(getDefaultSubscription());
}
/**
* Returns the unread count of voicemails for a subId
*/
- public int getVoiceMessageCountUsingSubId( long subId) {
+ public int getVoiceMessageCountForSubscriber( long subId) {
return getPhone(subId).getVoiceMessageCount();
}
@@ -1495,14 +1496,14 @@
*/
@Override
public int getNetworkType() {
- return getNetworkTypeUsingSubId(getDefaultSubscription());
+ return getNetworkTypeForSubscriber(getDefaultSubscription());
}
/**
* Returns the network type for a subId
*/
@Override
- public int getNetworkTypeUsingSubId(long subId) {
+ public int getNetworkTypeForSubscriber(long subId) {
return getPhone(subId).getServiceState().getDataNetworkType();
}
@@ -1511,14 +1512,14 @@
*/
@Override
public int getDataNetworkType() {
- return getDataNetworkTypeUsingSubId(getDefaultSubscription());
+ return getDataNetworkTypeForSubscriber(getDefaultSubscription());
}
/**
* Returns the data network type for a subId
*/
@Override
- public int getDataNetworkTypeUsingSubId(long subId) {
+ public int getDataNetworkTypeForSubscriber(long subId) {
return getPhone(subId).getServiceState().getDataNetworkType();
}
@@ -1527,14 +1528,14 @@
*/
@Override
public int getVoiceNetworkType() {
- return getVoiceNetworkTypeUsingSubId(getDefaultSubscription());
+ return getVoiceNetworkTypeForSubscriber(getDefaultSubscription());
}
/**
* Returns the Voice network type for a subId
*/
@Override
- public int getVoiceNetworkTypeUsingSubId(long subId) {
+ public int getVoiceNetworkTypeForSubscriber(long subId) {
return getPhone(subId).getServiceState().getVoiceNetworkType();
}
@@ -1562,10 +1563,10 @@
* or {@link Phone#LTE_ON_CDMA_TRUE}
*/
public int getLteOnCdmaMode() {
- return getLteOnCdmaModeUsingSubId(getDefaultSubscription());
+ return getLteOnCdmaModeForSubscriber(getDefaultSubscription());
}
- public int getLteOnCdmaModeUsingSubId(long subId) {
+ public int getLteOnCdmaModeForSubscriber(long subId) {
return getPhone(subId).getLteOnCdmaMode();
}
@@ -1929,52 +1930,94 @@
mPhone.getContext().getPackageManager(), intent);
}
+ private String getIccId(long subId) {
+ UiccCard card = getPhone(subId).getUiccCard();
+ if (card == null) {
+ loge("getIccId: No UICC");
+ return null;
+ }
+ String iccId = card.getIccId();
+ if (TextUtils.isEmpty(iccId)) {
+ loge("getIccId: ICC ID is null or empty.");
+ return null;
+ }
+ return iccId;
+ }
+
@Override
- public void enableSimplifiedNetworkSettings(long subId, boolean enable) {
+ public void enableSimplifiedNetworkSettingsForSubscriber(long subId, boolean enable) {
enforceModifyPermissionOrCarrierPrivilege();
- if (enable) {
- mSimplifiedNetworkSettings.add(subId);
- } else {
- mSimplifiedNetworkSettings.remove(subId);
+
+ String iccId = getIccId(subId);
+ if (iccId != null) {
+ String snsPrefKey = PREF_CARRIERS_SIMPLIFIED_NETWORK_SETTINGS_PREFIX + iccId;
+ SharedPreferences.Editor editor = carrierPrivilegeConfigs.edit();
+ if (enable) {
+ editor.putBoolean(snsPrefKey, true);
+ } else {
+ editor.remove(snsPrefKey);
+ }
+ editor.commit();
}
}
@Override
- public boolean getSimplifiedNetworkSettingsEnabled(long subId) {
+ public boolean getSimplifiedNetworkSettingsEnabledForSubscriber(long subId) {
enforceReadPermission();
- return mSimplifiedNetworkSettings.contains(subId);
+ String iccId = getIccId(subId);
+ if (iccId != null) {
+ String snsPrefKey = PREF_CARRIERS_SIMPLIFIED_NETWORK_SETTINGS_PREFIX + iccId;
+ return carrierPrivilegeConfigs.getBoolean(snsPrefKey, false);
+ }
+ return false;
}
@Override
- public void setLine1NumberForDisplay(long subId, String alphaTag, String number) {
+ public void setLine1NumberForDisplayForSubscriber(long subId, String alphaTag, String number) {
enforceModifyPermissionOrCarrierPrivilege();
- mAdnRecordsForDisplay.put(subId, new AdnRecord(alphaTag, number));
+
+ String iccId = getIccId(subId);
+ if (iccId != null) {
+ String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
+ SharedPreferences.Editor editor = carrierPrivilegeConfigs.edit();
+ if (alphaTag == null) {
+ editor.remove(alphaTagPrefKey);
+ } else {
+ editor.putString(alphaTagPrefKey, alphaTag);
+ }
+
+ String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
+ if (number == null) {
+ editor.remove(numberPrefKey);
+ } else {
+ editor.putString(numberPrefKey, number);
+ }
+ editor.commit();
+ }
}
@Override
public String getLine1NumberForDisplay(long subId) {
enforceReadPermission();
- if (!mAdnRecordsForDisplay.containsKey(subId)) {
- return null;
+
+ String iccId = getIccId(subId);
+ if (iccId != null) {
+ String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
+ return carrierPrivilegeConfigs.getString(numberPrefKey, null);
}
- AdnRecord adnRecord = mAdnRecordsForDisplay.get(subId);
- if (adnRecord.getNumber() == null || adnRecord.getNumber().isEmpty()) {
- return null;
- }
- return adnRecord.getNumber();
+ return null;
}
@Override
public String getLine1AlphaTagForDisplay(long subId) {
enforceReadPermission();
- if (!mAdnRecordsForDisplay.containsKey(subId)) {
- return null;
+
+ String iccId = getIccId(subId);
+ if (iccId != null) {
+ String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
+ return carrierPrivilegeConfigs.getString(alphaTagPrefKey, null);
}
- AdnRecord adnRecord = mAdnRecordsForDisplay.get(subId);
- if (adnRecord.getAlphaTag() == null || adnRecord.getAlphaTag().isEmpty()) {
- return null;
- }
- return adnRecord.getAlphaTag();
+ return null;
}
@Override
diff --git a/src/com/android/phone/settings/AccountSelectionPreference.java b/src/com/android/phone/settings/AccountSelectionPreference.java
index 32149ae..8469a18 100644
--- a/src/com/android/phone/settings/AccountSelectionPreference.java
+++ b/src/com/android/phone/settings/AccountSelectionPreference.java
@@ -16,7 +16,13 @@
package com.android.phone.settings;
+import com.android.phone.R;
+
+import android.app.AlertDialog;
import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.UserHandle;
import android.preference.ListPreference;
import android.preference.Preference;
import android.telecomm.PhoneAccountHandle;
@@ -31,8 +37,10 @@
public interface AccountSelectionListener {
boolean onAccountSelected(AccountSelectionPreference pref, PhoneAccountHandle account);
+ void onAccountSelectionDialogShow(AccountSelectionPreference pref);
}
+ private final Context mContext;
private AccountSelectionListener mListener;
private PhoneAccountHandle[] mAccounts;
private String[] mEntryValues;
@@ -40,11 +48,13 @@
public AccountSelectionPreference(Context context) {
super(context);
+ mContext = context;
setOnPreferenceChangeListener(this);
}
public AccountSelectionPreference(Context context, AttributeSet attrs) {
super(context, attrs);
+ mContext = context;
setOnPreferenceChangeListener(this);
}
@@ -93,4 +103,39 @@
}
return false;
}
+
+ /**
+ * Modifies the dialog to change the default "Cancel" button to "Choose Accounts", which
+ * triggers the {@link PhoneAccountSelectionPreferenceActivity} to be shown.
+ *
+ * @param builder The {@code AlertDialog.Builder}.
+ */
+ @Override
+ protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
+ // Notify the listener that the dialog is about to be built. This is important so that the
+ // list of enabled accounts can be updated prior to showing the dialog.
+ mListener.onAccountSelectionDialogShow(this);
+
+ final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int whichButton) {
+ showSelectPhoneAccounts();
+ }
+ };
+ builder.setNegativeButton(R.string.phone_accounts_choose_accounts, listener);
+ super.onPrepareDialogBuilder(builder);
+ }
+
+ /**
+ * Displays the {@link PhoneAccountSelectionPreferenceActivity} where the user is able to
+ * enable and disable phone accounts.
+ */
+ private void showSelectPhoneAccounts() {
+ Intent intent = new Intent(mContext, PhoneAccountSelectionPreferenceActivity.class);
+ intent.setAction(Intent.ACTION_MAIN);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
+ | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ mContext.startActivityAsUser(intent, null, UserHandle.CURRENT);
+ }
}
diff --git a/src/com/android/phone/settings/PhoneAccountSelectionPreferenceActivity.java b/src/com/android/phone/settings/PhoneAccountSelectionPreferenceActivity.java
new file mode 100644
index 0000000..7dd1190
--- /dev/null
+++ b/src/com/android/phone/settings/PhoneAccountSelectionPreferenceActivity.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2014 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.settings;
+
+import android.app.ActionBar;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceCategory;
+import android.preference.PreferenceFragment;
+import android.preference.SwitchPreference;
+import android.telecomm.PhoneAccount;
+import android.telecomm.PhoneAccountHandle;
+import android.telecomm.TelecommManager;
+
+import com.android.internal.util.CharSequences;
+import com.android.phone.R;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * Preference activity used to facilitate enabling and disabling phone accounts by the user.
+ */
+public class PhoneAccountSelectionPreferenceActivity extends PreferenceActivity {
+
+ /**
+ * Preference fragment containing a list of all {@link PhoneAccount}s in the form of switches
+ * the user can use to enable or disable accounts.
+ */
+ public static class PhoneAccountSelectionPreferenceFragment extends PreferenceFragment
+ implements Preference.OnPreferenceChangeListener {
+ private static final String CATEGORY_PHONE_ACCOUNTS_KEY = "phone_accounts_list";
+
+ private TelecommManager mTelecommManager;
+ private PreferenceCategory mPhoneAccountsCategory;
+
+ /**
+ * Represents a single {@link PhoneAccount} for the purpose enabling and disabling.
+ */
+ static class PhoneAccountPreference extends SwitchPreference {
+ private PhoneAccountHandle mPhoneAccountHandle;
+ private boolean mPreviousState;
+
+ public PhoneAccountPreference(Context context, PhoneAccount phoneAccount) {
+ super(context);
+
+ setPhoneAccount(phoneAccount);
+ }
+
+ /**
+ * Configures the {@code PhoneAccountPreference} for the passed in {@link PhoneAccount}.
+ *
+ * @param phoneAccount The phone account.
+ */
+ private void setPhoneAccount(PhoneAccount phoneAccount) {
+ mPhoneAccountHandle = phoneAccount.getAccountHandle();
+ mPreviousState = phoneAccount.isEnabled();
+ this.setTitle(phoneAccount.getLabel());
+ this.setChecked(mPreviousState);
+ }
+
+ public boolean getPreviousState() {
+ return mPreviousState;
+ }
+
+ public PhoneAccountHandle getPhoneAccountHandle() {
+ return mPhoneAccountHandle;
+ }
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ addPreferencesFromResource(R.xml.phone_account_selection);
+ mPhoneAccountsCategory = (PreferenceCategory) findPreference(
+ CATEGORY_PHONE_ACCOUNTS_KEY);
+ mTelecommManager = TelecommManager.from(this.getActivity());
+
+ List<PhoneAccount> phoneAccounts = mTelecommManager.getAllPhoneAccounts();
+ Collections.sort(phoneAccounts, new Comparator<PhoneAccount>() {
+ @Override
+ public int compare(PhoneAccount o1, PhoneAccount o2) {
+ return CharSequences.compareToIgnoreCase(o1.getLabel(), o2.getLabel());
+ }
+ });
+
+ for (PhoneAccount phoneAccount : phoneAccounts) {
+ // Do not add Sim PhoneAccounts.
+ if (phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
+ continue;
+ }
+
+ PhoneAccountPreference phoneAccountPreference = new PhoneAccountPreference(
+ getActivity(), phoneAccount);
+ phoneAccountPreference.setOnPreferenceChangeListener(this);
+ phoneAccountPreference.setEnabled(!phoneAccount.hasCapabilities(
+ PhoneAccount.CAPABILITY_ALWAYS_ENABLED));
+ mPhoneAccountsCategory.addPreference(phoneAccountPreference);
+ }
+ }
+
+ /**
+ * Handles changes to preferences
+ * @param preference The preference which changed.
+ * @param newValue The new value of the preference.
+ * @return
+ */
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ if (preference instanceof PhoneAccountPreference) {
+ PhoneAccountPreference phoneAccountPreference = (PhoneAccountPreference) preference;
+ boolean newState = Boolean.valueOf(newValue.toString()).booleanValue();
+
+ if (newState != phoneAccountPreference.getPreviousState()) {
+ mTelecommManager.setPhoneAccountEnabled(
+ phoneAccountPreference.getPhoneAccountHandle(), newState);
+ }
+ return true;
+ }
+ return false;
+ }
+ }
+
+ @Override
+ public void onBuildHeaders(List<Header> target) {
+ loadHeadersFromResource(R.xml.phone_account_selection_activity, target);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ setTitle(getResources().getString(R.string.call_settings));
+ ActionBar actionBar = getActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayShowHomeEnabled(false);
+ actionBar.setDisplayHomeAsUpEnabled(false);
+ }
+
+ // By default, show the main fragment.
+ Intent intent = getIntent();
+ if (intent.getStringArrayExtra(EXTRA_SHOW_FRAGMENT) == null) {
+ getIntent().putExtra(EXTRA_SHOW_FRAGMENT,
+ PhoneAccountSelectionPreferenceFragment.class.getName());
+ }
+
+ super.onCreate(savedInstanceState);
+ }
+
+ @Override
+ public boolean isValidFragment(String fragmentName) {
+ return true;
+ }
+}
diff --git a/src/com/android/services/telephony/TelecommAccountRegistry.java b/src/com/android/services/telephony/TelecommAccountRegistry.java
index 0aba6b4..f6220bb 100644
--- a/src/com/android/services/telephony/TelecommAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecommAccountRegistry.java
@@ -25,13 +25,16 @@
import android.telecomm.PhoneAccount;
import android.telecomm.PhoneAccountHandle;
import android.telecomm.TelecommManager;
+import android.telephony.SubInfoRecord;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import android.text.TextUtils;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.PhoneProxy;
import com.android.internal.telephony.TelephonyIntents;
+import com.android.phone.R;
import java.util.Arrays;
import java.util.LinkedList;
@@ -42,14 +45,21 @@
* removal of SIMs and SIP accounts.
*/
final class TelecommAccountRegistry {
+ private static final boolean DBG = false; /* STOP SHIP if true */
+
+ // Slot IDs are zero based indices but the numbered icons represent the first, second,
+ // etc... SIM in the device. So that means that index 0 is SIM 1, index 1 is SIM 2 and so on.
private final static int[] phoneAccountIcons = {
- com.android.phone.R.drawable.ic_multi_sim,
- com.android.phone.R.drawable.ic_multi_sim1,
- com.android.phone.R.drawable.ic_multi_sim2,
- com.android.phone.R.drawable.ic_multi_sim3,
- com.android.phone.R.drawable.ic_multi_sim4
+ R.drawable.ic_multi_sim1,
+ R.drawable.ic_multi_sim2,
+ R.drawable.ic_multi_sim3,
+ R.drawable.ic_multi_sim4
};
+ // This icon is the one that is used when the Slot ID that we have for a particular SIM
+ // is not supported, i.e. SubscriptionManager.INVALID_SLOT_ID or the 5th SIM in a phone.
+ private final static int defaultPhoneAccountIcon = R.drawable.ic_multi_sim;
+
private final class AccountEntry {
private final Phone mPhone;
private final PhoneAccount mAccount;
@@ -64,7 +74,6 @@
}
void teardown() {
- mTelecommManager.unregisterPhoneAccount(mAccount.getAccountHandle());
mIncomingCallNotifier.teardown();
}
@@ -81,8 +90,7 @@
// Populate the phone account data.
long subId = mPhone.getSubId();
- int slotId = mPhone.getPhoneId() + 1;
- String line1Number = telephonyManager.getLine1Number(subId);
+ String line1Number = telephonyManager.getLine1NumberForSubscriber(subId);
if (line1Number == null) {
line1Number = "";
}
@@ -90,33 +98,78 @@
if (subNumber == null) {
subNumber = "";
}
- String label = isEmergency
- ? "Emergency calls"
- : dummyPrefix + "SIM " + slotId;
- String description = isEmergency
- ? "Emergency calling only"
- : dummyPrefix + "SIM card in slot " + slotId;
+
+ String subDisplayName = null;
+ // We can only get the real slotId from the SubInfoRecord, we can't calculate the
+ // slotId from the subId or the phoneId in all instances.
+ SubInfoRecord record = SubscriptionManager.getSubInfoForSubscriber(subId);
+ int slotId = SubscriptionManager.INVALID_SLOT_ID;
+ if (record != null) {
+ subDisplayName = record.displayName;
+ slotId = record.slotId;
+ }
+
+ String slotIdString;
+ if (SubscriptionManager.isValidSlotId(slotId)) {
+ slotIdString = Integer.toString(slotId);
+ } else {
+ slotIdString = mContext.getResources().getString(R.string.unknown);
+ }
+
+ if (TextUtils.isEmpty(subDisplayName)) {
+ // Either the sub record is not there or it has an empty display name.
+ Log.w(this, "Could not get a display name for subid: %d", subId);
+ subDisplayName = mContext.getResources().getString(
+ R.string.sim_description_default, slotIdString);
+ }
+
+ // The label is user-visible so let's use the display name that the user may
+ // have set in Settings->Sim cards.
+ String label = isEmergency ?
+ mContext.getResources().getString(R.string.sim_label_emergency_calls) :
+ dummyPrefix + subDisplayName;
+ String description = isEmergency ?
+ mContext.getResources().getString(R.string.sim_description_emergency_calls) :
+ dummyPrefix + mContext.getResources().getString(
+ R.string.sim_description_default, slotIdString);
+
+ // By default all SIM phone accounts can place emergency calls.
+ int capabilities = PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION |
+ PhoneAccount.CAPABILITY_CALL_PROVIDER |
+ PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS;
+
+ // Indicate the emergency calling PhoneAccount is ALWAYS enabled. This capability is
+ // important to ensure the emergency-only PhoneAccount cannot be disabled.
+ if (isEmergency) {
+ capabilities |= PhoneAccount.CAPABILITY_ALWAYS_ENABLED;
+ }
+
PhoneAccount account = PhoneAccount.builder(phoneAccountHandle, label)
.setAddress(Uri.fromParts(PhoneAccount.SCHEME_TEL, line1Number, null))
.setSubscriptionAddress(
Uri.fromParts(PhoneAccount.SCHEME_TEL, subNumber, null))
- .setCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION |
- PhoneAccount.CAPABILITY_CALL_PROVIDER)
+ .setCapabilities(capabilities)
.setIconResId(getPhoneAccountIcon(slotId))
.setShortDescription(description)
.setSupportedUriSchemes(Arrays.asList(
PhoneAccount.SCHEME_TEL, PhoneAccount.SCHEME_VOICEMAIL))
+ .setEnabled(true)
.build();
// Register with Telecomm and put into the account entry.
mTelecommManager.registerPhoneAccount(account);
return account;
}
+
+ public PhoneAccountHandle getPhoneAccountHandle() {
+ return mAccount != null ? mAccount.getAccountHandle() : null;
+ }
}
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
+ boolean rebuildAccounts = false;
String action = intent.getAction();
if (TelephonyIntents.ACTION_SUBINFO_RECORD_UPDATED.equals(action)) {
int status = intent.getIntExtra(
@@ -126,6 +179,15 @@
// Anytime the SIM state changes...rerun the setup
// We rely on this notification even when the status is EXTRA_VALUE_NOCHANGE,
// so we explicitly do not check for that here.
+ rebuildAccounts = true;
+ } else if (TelephonyIntents.ACTION_SUBINFO_CONTENT_CHANGE.equals(action)) {
+ String columnName = intent.getStringExtra(TelephonyIntents.EXTRA_COLUMN_NAME);
+ String stringContent = intent.getStringExtra(TelephonyIntents.EXTRA_STRING_CONTENT);
+ Log.v(this, "SUBINFO_CONTENT_CHANGE: Column: %s Content: %s",
+ columnName, stringContent);
+ rebuildAccounts = true;
+ }
+ if (rebuildAccounts) {
tearDownAccounts();
setupAccounts();
}
@@ -153,11 +215,12 @@
* Sets up all the phone accounts for SIMs on first boot.
*/
void setupOnBoot() {
- IntentFilter intentFilter =
- new IntentFilter(TelephonyIntents.ACTION_SUBINFO_RECORD_UPDATED);
+ // We need to register for both types of intents if we want to see added/removed Subs
+ // along with changes to a given Sub.
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(TelephonyIntents.ACTION_SUBINFO_RECORD_UPDATED);
+ intentFilter.addAction(TelephonyIntents.ACTION_SUBINFO_CONTENT_CHANGE);
mContext.registerReceiver(mReceiver, intentFilter);
-
- setupAccounts();
}
static PhoneAccountHandle makePstnPhoneAccountHandle(Phone phone) {
@@ -174,22 +237,43 @@
return new PhoneAccountHandle(pstnConnectionServiceName, id);
}
- private void clearCurrentTelephonyAccounts() {
+ /**
+ * Determines if the list of {@link AccountEntry}(s) contains an {@link AccountEntry} with a
+ * specified {@link PhoneAccountHandle}.
+ *
+ * @param handle The {@link PhoneAccountHandle}.
+ * @return {@code True} if an entry exists.
+ */
+ private boolean hasAccountEntryForPhoneAccount(PhoneAccountHandle handle) {
+ for (AccountEntry entry : mAccounts) {
+ if (entry.getPhoneAccountHandle().equals(handle)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Un-registers any {@link PhoneAccount}s which are no longer present in the list
+ * {@code AccountEntry}(s).
+ */
+ private void cleanupPhoneAccounts() {
ComponentName telephonyComponentName =
new ComponentName(mContext, TelephonyConnectionService.class);
- List<PhoneAccountHandle> accountHandles = mTelecommManager.getEnabledPhoneAccounts();
+
+ List<PhoneAccountHandle> accountHandles = mTelecommManager.getAllPhoneAccountHandles();
for (PhoneAccountHandle handle : accountHandles) {
- if (telephonyComponentName.equals(handle.getComponentName())) {
+ if (telephonyComponentName.equals(handle.getComponentName()) &&
+ !hasAccountEntryForPhoneAccount(handle)) {
+ Log.d(this, "Unregistering phone account %s.", handle);
mTelecommManager.unregisterPhoneAccount(handle);
}
}
}
private void setupAccounts() {
- // Before we do anything, we need to clear whatever entries we registered at boot.
- clearCurrentTelephonyAccounts();
-
- // Go through SIM-based phones and register ourselves
+ // Go through SIM-based phones and register ourselves -- registering an existing account
+ // will cause the existing entry to be replaced.
Phone[] phones = PhoneFactory.getPhones();
Log.d(this, "Found %d phones. Attempting to register.", phones.length);
for (Phone phone : phones) {
@@ -209,19 +293,22 @@
}
// Add a fake account entry.
- if (phones.length > 0 && "TRUE".equals(System.getProperty("dummy_sim"))) {
+ if ( DBG && phones.length > 0 && "TRUE".equals(System.getProperty("dummy_sim"))) {
mAccounts.add(new AccountEntry(phones[0], false /* emergency */, true /* isDummy */));
}
- // TODO: Add SIP accounts.
+ // Clean up any PhoneAccounts that are no longer relevant
+ cleanupPhoneAccounts();
}
private int getPhoneAccountIcon(int index) {
- if (index < TelecommAccountRegistry.phoneAccountIcons.length) {
+ // A valid slot id doesn't necessarily mean that we have an icon for it.
+ if (SubscriptionManager.isValidSlotId(index) &&
+ index < TelecommAccountRegistry.phoneAccountIcons.length) {
return TelecommAccountRegistry.phoneAccountIcons[index];
}
- // default blank icon
- return TelecommAccountRegistry.phoneAccountIcons[0];
+ // Invalid indices get the default icon that has no number associated with it.
+ return defaultPhoneAccountIcon;
}
private void tearDownAccounts() {