aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk6
-rw-r--r--resources/res/values/config.xml5
-rw-r--r--src/java/android/provider/Telephony.java195
-rw-r--r--src/java/android/telephony/SmsManager.java16
-rw-r--r--src/java/android/telephony/SmsMessage.java2
-rw-r--r--src/java/com/android/internal/telephony/BaseCommands.java12
-rw-r--r--src/java/com/android/internal/telephony/CallManager.java40
-rw-r--r--src/java/com/android/internal/telephony/CarrierAppUtils.java67
-rw-r--r--src/java/com/android/internal/telephony/CommandsInterface.java23
-rw-r--r--src/java/com/android/internal/telephony/InboundSmsHandler.java86
-rwxr-xr-xsrc/java/com/android/internal/telephony/Phone.java30
-rw-r--r--src/java/com/android/internal/telephony/PhoneBase.java43
-rw-r--r--src/java/com/android/internal/telephony/PhoneFactory.java57
-rw-r--r--src/java/com/android/internal/telephony/PhoneProxy.java8
-rw-r--r--src/java/com/android/internal/telephony/RIL.java409
-rw-r--r--src/java/com/android/internal/telephony/SubscriptionController.java57
-rw-r--r--src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java138
-rw-r--r--src/java/com/android/internal/telephony/TelephonyPluginDelegate.java31
-rw-r--r--src/java/com/android/internal/telephony/UiccSmsController.java7
-rw-r--r--src/java/com/android/internal/telephony/cdma/CDMAPhone.java10
-rw-r--r--src/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java7
-rw-r--r--src/java/com/android/internal/telephony/dataconnection/DataCallResponse.java2
-rw-r--r--src/java/com/android/internal/telephony/dataconnection/DataConnection.java5
-rwxr-xr-xsrc/java/com/android/internal/telephony/dataconnection/DcController.java4
-rw-r--r--src/java/com/android/internal/telephony/dataconnection/DcTracker.java8
-rw-r--r--src/java/com/android/internal/telephony/dataconnection/DctController.java5
-rw-r--r--src/java/com/android/internal/telephony/gsm/GSMPhone.java4
-rw-r--r--src/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java8
-rw-r--r--src/java/com/android/internal/telephony/gsm/SuppServiceNotification.java5
-rw-r--r--src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java2
-rw-r--r--src/java/com/android/internal/telephony/imsphone/ImsPhoneCommandInterface.java2
-rw-r--r--src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java2
-rw-r--r--src/java/com/android/internal/telephony/sip/SipCommandInterface.java1
-rw-r--r--src/java/com/android/internal/telephony/test/SimulatedCommands.java2
-rw-r--r--src/java/com/android/internal/telephony/uicc/IccRecords.java17
-rw-r--r--src/java/com/android/internal/telephony/uicc/RuimRecords.java13
-rw-r--r--src/java/com/android/internal/telephony/uicc/SIMRecords.java29
-rw-r--r--src/java/com/android/internal/telephony/uicc/UICCConfig.java87
-rw-r--r--src/java/com/android/internal/telephony/uicc/UiccCard.java50
-rw-r--r--src/java/com/android/internal/telephony/uicc/UiccCardApplication.java5
-rw-r--r--src/java/com/android/internal/telephony/uicc/UiccController.java10
-rw-r--r--src/java/com/android/internal/telephony/util/BlacklistUtils.java262
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/CarrierAppUtilsTest.java31
43 files changed, 1566 insertions, 237 deletions
diff --git a/Android.mk b/Android.mk
index 449faa00a..ff1cf59d3 100644
--- a/Android.mk
+++ b/Android.mk
@@ -25,6 +25,12 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src/java) \
$(call all-logtags-files-under, src/java)
LOCAL_JAVA_LIBRARIES := voip-common ims-common
+LOCAL_REQUIRED_MODULES := telresources
+
+ifneq ($(BOARD_RIL_CLASS),)
+LOCAL_SRC_FILES += $(call find-other-java-files,$(BOARD_RIL_CLASS))
+endif
+
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := telephony-common
diff --git a/resources/res/values/config.xml b/resources/res/values/config.xml
index 3ade5cc6d..eb6a35fd1 100644
--- a/resources/res/values/config.xml
+++ b/resources/res/values/config.xml
@@ -43,6 +43,11 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<bool name="config_reject_call_via_sms_enabled">true</bool>
<!-- To disable/enable call barring requests over IMS -->
<bool name="config_enable_callbarring_over_ims">false</bool>
+ <!--The .jar file name which has the extended implementation
+ of telephony base classes.-->
+ <string name="telephony_plugin_jar_name" translatable="false"></string>
+ <!--Fully qualified class name of telephony extended plugin.-->
+ <string name="telephony_plugin_class_name" translatable="false"></string>
<!-- When set to true, this config enables reading and displaying
the contents of EF_SDN present in SIM -->
<bool name="config_enable_displaying_sdn">false</bool>
diff --git a/src/java/android/provider/Telephony.java b/src/java/android/provider/Telephony.java
index 81577804f..5e5e89bd1 100644
--- a/src/java/android/provider/Telephony.java
+++ b/src/java/android/provider/Telephony.java
@@ -35,8 +35,10 @@ import android.util.Patterns;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.SmsApplication;
-
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -842,6 +844,51 @@ public final class Telephony {
public static final int RESULT_SMS_DUPLICATED = 5;
/**
+ * Used internally: The sender of the SMS was blacklisted
+ * for not being listed in the contact list
+ * @hide
+ */
+ public static final int RESULT_SMS_BLACKLISTED_UNKNOWN = 6;
+
+ /**
+ * Used internally: The sender of the SMS was blacklisted
+ * for being listed in the blacklist
+ * @hide
+ */
+ public static final int RESULT_SMS_BLACKLISTED_LIST = 7;
+
+ /**
+ * Used internally: The sender of the SMS was blacklisted
+ * for matching a blacklist regex entry
+ * @hide
+ */
+ public static final int RESULT_SMS_BLACKLISTED_REGEX = 8;
+
+ /**
+ * Used internally:
+ * Broadcast Action: A new protected text-based SMS message has been received
+ * by the device. This intent will be delivered to all registered
+ * receivers who possess {@link android.Manifest.permission#RECEIVE_PROTECTED_SMS}.
+ * These apps SHOULD NOT write the message or notify the user.
+ * The intent will have the following extra values:
+ * </p>
+ *
+ * <ul>
+ * <li><em>"pdus"</em> - An Object[] of byte[]s containing the PDUs
+ * that make up the message.</li>
+ * </ul>
+ *
+ * <p>The extra values can be extracted using
+ * {@link #getMessagesFromIntent(Intent)}.</p>
+ *
+ * <p>If a BroadcastReceiver encounters an error while processing
+ * this intent it should set the result code appropriately.</p>
+ * @hide
+ */
+ public static final String PROTECTED_SMS_RECEIVED_ACTION =
+ "android.provider.Telephony.ACTION_PROTECTED_SMS_RECEIVED";
+
+ /**
* Activity action: Ask the user to change the default
* SMS application. This will show a dialog that asks the
* user whether they want to replace the current default
@@ -1141,6 +1188,49 @@ public final class Telephony {
}
return msgs;
}
+
+ /**
+ * Read the normalized addresses out of PDUs
+ * @param pdus bytes for PDUs
+ * @param format the format of the message
+ * @return a list of Addresses for the PDUs
+ * @hide
+ */
+ public static List<String> getNormalizedAddressesFromPdus(byte[][] pdus,
+ String format) {
+ int pduCount = pdus.length;
+ SmsMessage[] msgs = new SmsMessage[pduCount];
+ List<String> addresses = new ArrayList<String>();
+
+ for (int i = 0; i < pduCount; i++) {
+ byte[] pdu = (byte[]) pdus[i];
+ msgs[i] = SmsMessage.createFromPdu(pdu, format);
+ String originatingAddress = msgs[i].getOriginatingAddress();
+ if (!TextUtils.isEmpty(originatingAddress)) {
+ String normalized = normalizeDigitsOnly(originatingAddress);
+ addresses.add(normalized);
+ }
+ }
+ return addresses;
+ }
+
+ private static String normalizeDigitsOnly(String number) {
+ return normalizeDigits(number, false /* strip non-digits */).toString();
+ }
+
+ private static StringBuilder normalizeDigits(String number, boolean keepNonDigits) {
+ StringBuilder normalizedDigits = new StringBuilder(number.length());
+ for (char c : number.toCharArray()) {
+ int digit = Character.digit(c, 10);
+ if (digit != -1) {
+ normalizedDigits.append(digit);
+ } else if (keepNonDigits) {
+ normalizedDigits.append(c);
+ }
+ }
+ return normalizedDigits;
+ }
+
}
}
@@ -2313,6 +2403,13 @@ public final class Telephony {
}
/**
+ * The column that specifies number of messages of type.
+ * @hide
+ */
+ public static final String TRANSPORT_TYPE_COUNT_COLUMN =
+ "transport_type_count";
+
+ /**
* The column to distinguish SMS and MMS messages in query results.
*/
public static final String TYPE_DISCRIMINATOR_COLUMN =
@@ -2760,6 +2857,30 @@ public final class Telephony {
public static final String USER_VISIBLE = "user_visible";
/**
+ * <P>Type: INTEGER (boolean)</P>
+ * @hide
+ */
+ public static final String READ_ONLY = "read_only";
+
+ /**
+ * <P>Type: TEXT</P>
+ * @hide
+ */
+ public static final String PPP_NUMBER = "ppp_number";
+
+ /**
+ * <P>Type: TEXT</P>
+ * @hide
+ */
+ public static final String LOCALIZED_NAME = "localized_name";
+
+ /**
+ * <P>Type: TEXT</P>
+ * @hide
+ */
+ public static final String VISIT_AREA = "visit_area";
+
+ /**
* Following are possible values for the EDITED field
* @hide
*/
@@ -3002,4 +3123,76 @@ public final class Telephony {
public static final String STATE = "state";
}
+
+ /**
+ * Contains phone numbers that are blacklisted
+ * for phone and/or message purposes.
+ * @hide
+ */
+ public static final class Blacklist implements BaseColumns {
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI =
+
+ Uri.parse("content://blacklist");
+
+ /**
+ * The content:// style URL for filtering this table by number.
+ * When using this, make sure the number is correctly encoded
+ * when appended to the Uri.
+ */
+ public static final Uri CONTENT_FILTER_BYNUMBER_URI =
+ Uri.parse("content://blacklist/bynumber");
+
+ /**
+ * The content:// style URL for filtering this table on phone numbers
+ */
+ public static final Uri CONTENT_PHONE_URI =
+ Uri.parse("content://blacklist/phone");
+
+ /**
+ * The content:// style URL for filtering this table on message numbers
+ */
+ public static final Uri CONTENT_MESSAGE_URI =
+ Uri.parse("content://blacklist/message");
+
+
+ /**
+ * Query parameter used to match numbers by regular-expression like
+ * matching. Supported are the '*' and the '.' operators.
+ * <p>
+ * TYPE: boolean
+ */
+ public static final String REGEX_KEY = "regex";
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "number ASC";
+
+ /**
+ * The phone number as the user entered it.
+ * <P>Type: TEXT</P>
+ */
+ public static final String NUMBER = "number";
+
+ /**
+ * Whether the number contains a regular expression pattern
+ * <P>Type: BOOLEAN (read only)</P>
+ */
+ public static final String IS_REGEX = "is_regex";
+
+ /**
+ * Blacklisting mode for phone calls
+ * <P>Type: INTEGER (int)</P>
+ */
+ public static final String PHONE_MODE = "phone";
+
+ /**
+ * Blacklisting mode for messages
+ * <P>Type: INTEGER (int)</P>
+ */
+ public static final String MESSAGE_MODE = "message";
+ }
}
diff --git a/src/java/android/telephony/SmsManager.java b/src/java/android/telephony/SmsManager.java
index c2e230003..30c0bb17d 100644
--- a/src/java/android/telephony/SmsManager.java
+++ b/src/java/android/telephony/SmsManager.java
@@ -1247,6 +1247,22 @@ public final class SmsManager {
}
/**
+ * Set SMS prompt property, enabled or not
+ * @hide
+ */
+ public void setSMSPromptEnabled(boolean bool) {
+ ISms iccISms = null;
+ try {
+ iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
+ iccISms.setSMSPromptEnabled(bool);
+ } catch (RemoteException ex) {
+ //ignore it
+ } catch (NullPointerException ex) {
+ //ignore it
+ }
+ }
+
+ /**
* Get the capacity count of sms on Icc card
*
* @return the capacity count of sms on Icc card
diff --git a/src/java/android/telephony/SmsMessage.java b/src/java/android/telephony/SmsMessage.java
index 1d05468dd..03676b793 100644
--- a/src/java/android/telephony/SmsMessage.java
+++ b/src/java/android/telephony/SmsMessage.java
@@ -555,7 +555,7 @@ public class SmsMessage {
* form or null if unavailable
*/
public String getOriginatingAddress() {
- return mWrappedSmsMessage.getOriginatingAddress();
+ return mWrappedSmsMessage != null ? mWrappedSmsMessage.getOriginatingAddress() : null;
}
/**
diff --git a/src/java/com/android/internal/telephony/BaseCommands.java b/src/java/com/android/internal/telephony/BaseCommands.java
index 7d3e1bd50..b36dca965 100644
--- a/src/java/com/android/internal/telephony/BaseCommands.java
+++ b/src/java/com/android/internal/telephony/BaseCommands.java
@@ -849,8 +849,7 @@ public abstract class BaseCommands implements CommandsInterface {
return mRilVersion;
}
- public void setUiccSubscription(int slotId, int appIndex, int subId, int subStatus,
- Message response) {
+ public void setUiccSubscription(int appIndex, boolean activate, Message response) {
}
public void setDataAllowed(boolean allowed, Message response) {
@@ -924,4 +923,13 @@ public abstract class BaseCommands implements CommandsInterface {
@Override
public void getAtr(Message response) {}
+
+ /**
+ * @hide
+ */
+ @Override
+ public int getLteOnGsmMode() {
+ return TelephonyManager.getLteOnGsmModeStatic();
+ }
+
}
diff --git a/src/java/com/android/internal/telephony/CallManager.java b/src/java/com/android/internal/telephony/CallManager.java
index 98d417511..2e975186a 100644
--- a/src/java/com/android/internal/telephony/CallManager.java
+++ b/src/java/com/android/internal/telephony/CallManager.java
@@ -86,6 +86,7 @@ public final class CallManager {
// FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
//private static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 121;
private static final int EVENT_TTY_MODE_RECEIVED = 122;
+ private static final int EVENT_SUPP_SERVICE_NOTIFY = 123;
// Singleton instance
private static final CallManager INSTANCE = new CallManager();
@@ -175,6 +176,9 @@ public final class CallManager {
protected final RegistrantList mSubscriptionInfoReadyRegistrants
= new RegistrantList();
+ protected final RegistrantList mSuppServiceNotifyRegistrants
+ = new RegistrantList();
+
protected final RegistrantList mSuppServiceFailedRegistrants
= new RegistrantList();
@@ -651,6 +655,11 @@ public final class CallManager {
// FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
//phone.registerForRadioOffOrNotAvailable(handler, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
+ // for events supported only by GSM phone
+ if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM) {
+ phone.registerForSuppServiceNotification(handler, EVENT_SUPP_SERVICE_NOTIFY, null);
+ }
+
// for events supported only by GSM, CDMA and IMS phone
if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM ||
phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA ||
@@ -703,6 +712,11 @@ public final class CallManager {
// FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
//phone.unregisterForRadioOffOrNotAvailable(handler);
+ // for events supported only by GSM phone
+ if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM) {
+ phone.unregisterForSuppServiceNotification(handler);
+ }
+
// for events supported only by GSM, CDMA and IMS phone
if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM ||
phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA ||
@@ -1601,6 +1615,28 @@ public final class CallManager {
}
/**
+ * Register for supplementary service notifications.
+ * Message.obj will contain an AsyncResult.
+ *
+ * @param h Handler that receives the notification message.
+ * @param what User-defined message code.
+ * @param obj User object.
+ */
+ public void registerForSuppServiceNotification(Handler h, int what, Object obj) {
+ mSuppServiceNotifyRegistrants.addUnique(h, what, obj);
+ }
+
+ /**
+ * Unregister for supplementary service notifications.
+ * Extraneous calls are tolerated silently
+ *
+ * @param h Handler to be removed from the registrant list.
+ */
+ public void unregisterForSuppServiceNotification(Handler h) {
+ mSuppServiceNotifyRegistrants.remove(h);
+ }
+
+ /**
* Register for notifications when a supplementary service attempt fails.
* Message.obj will contain an AsyncResult.
*
@@ -2390,6 +2426,10 @@ public final class CallManager {
if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SUBSCRIPTION_INFO_READY)");
mSubscriptionInfoReadyRegistrants.notifyRegistrants((AsyncResult) msg.obj);
break;
+ case EVENT_SUPP_SERVICE_NOTIFY:
+ if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SUPP_SERVICE_NOTIFY)");
+ mSuppServiceNotifyRegistrants.notifyRegistrants((AsyncResult) msg.obj);
+ break;
case EVENT_SUPP_SERVICE_FAILED:
if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SUPP_SERVICE_FAILED)");
mSuppServiceFailedRegistrants.notifyRegistrants((AsyncResult) msg.obj);
diff --git a/src/java/com/android/internal/telephony/CarrierAppUtils.java b/src/java/com/android/internal/telephony/CarrierAppUtils.java
index 4be914c99..45425d0ec 100644
--- a/src/java/com/android/internal/telephony/CarrierAppUtils.java
+++ b/src/java/com/android/internal/telephony/CarrierAppUtils.java
@@ -27,6 +27,7 @@ import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
/**
@@ -52,6 +53,10 @@ public final class CarrierAppUtils {
* in the default state (e.g. not explicitly DISABLED/DISABLED_BY_USER/ENABLED), or we enable if
* the app is carrier privileged and in either the default state or DISABLED_UNTIL_USED.
*
+ * In addition, a list of permanently enabled carrier apps is packaged with the system and read
+ * here. All permanently enabled carrier apps are treated the same as the SIM enabled carrier
+ * apps here.
+ *
* When enabling a carrier app we also grant it default permissions.
*
* This method is idempotent and is safe to be called at any time; it should be called once at
@@ -65,26 +70,39 @@ public final class CarrierAppUtils {
}
String[] systemCarrierAppsDisabledUntilUsed = Resources.getSystem().getStringArray(
com.android.internal.R.array.config_disabledUntilUsedPreinstalledCarrierApps);
+ String[] systemCarrierAppsEnabled = Resources.getSystem().getStringArray(
+ com.android.internal.R.array.config_enabledPreinstalledCarrierApps);
disableCarrierAppsUntilPrivileged(callingPackage, packageManager, telephonyManager, userId,
- systemCarrierAppsDisabledUntilUsed);
+ systemCarrierAppsDisabledUntilUsed, systemCarrierAppsEnabled);
}
// Must be public b/c framework unit tests can't access package-private methods.
@VisibleForTesting
public static void disableCarrierAppsUntilPrivileged(String callingPackage,
IPackageManager packageManager, TelephonyManager telephonyManager, int userId,
- String[] systemCarrierAppsDisabledUntilUsed) {
+ String[] systemCarrierAppsDisabledUntilUsed, String[] systemCarrierAppsEnabled) {
List<ApplicationInfo> candidates = getDefaultCarrierAppCandidatesHelper(packageManager,
- userId, systemCarrierAppsDisabledUntilUsed);
+ userId, systemCarrierAppsDisabledUntilUsed, systemCarrierAppsEnabled);
if (candidates == null || candidates.isEmpty()) {
return;
}
+ HashSet<String> enabledCarrierAppsSet = new HashSet<>(systemCarrierAppsEnabled.length);
+ for (String packageName : systemCarrierAppsEnabled) {
+ enabledCarrierAppsSet.add(packageName);
+ }
+
List<String> enabledCarrierPackages = new ArrayList<>();
try {
for (ApplicationInfo ai : candidates) {
String packageName = ai.packageName;
+
+ // Enabled carrier apps are already enabled, so continue
+ if (enabledCarrierAppsSet.contains(ai.packageName)) {
+ continue;
+ }
+
boolean hasPrivileges =
telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(packageName) ==
TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
@@ -118,6 +136,11 @@ public final class CarrierAppUtils {
}
}
+ // Add all permanently enabled packages to the enabled list
+ for (String enabledPackageName : systemCarrierAppsEnabled) {
+ enabledCarrierPackages.add(enabledPackageName);
+ }
+
if (!enabledCarrierPackages.isEmpty()) {
// Since we enabled at least one app, ensure we grant default permissions to those
// apps.
@@ -135,7 +158,8 @@ public final class CarrierAppUtils {
*
* This is the subset of apps returned by
* {@link #getDefaultCarrierAppCandidates(IPackageManager, int)} which currently have carrier
- * privileges per the SIM(s) inserted in the device.
+ * privileges per the SIM(s) inserted in the device. All permanent system enabled carrier
+ * apps are always included in the returned list.
*/
public static List<ApplicationInfo> getDefaultCarrierApps(IPackageManager packageManager,
TelephonyManager telephonyManager, int userId) {
@@ -145,6 +169,13 @@ public final class CarrierAppUtils {
return null;
}
+ String[] systemCarrierAppsEnabled = Resources.getSystem().getStringArray(
+ com.android.internal.R.array.config_enabledPreinstalledCarrierApps);
+ HashSet<String> enabledCarrierAppsSet = new HashSet<>(systemCarrierAppsEnabled.length);
+ for (String packageName : systemCarrierAppsEnabled) {
+ enabledCarrierAppsSet.add(packageName);
+ }
+
// Filter out apps without carrier privileges.
// Iterate from the end to avoid creating an Iterator object and because we will be removing
// elements from the list as we pass through it.
@@ -154,7 +185,7 @@ public final class CarrierAppUtils {
boolean hasPrivileges =
telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(packageName) ==
TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
- if (!hasPrivileges) {
+ if (!hasPrivileges && !enabledCarrierAppsSet.contains(packageName)) {
candidates.remove(i);
}
}
@@ -168,7 +199,8 @@ public final class CarrierAppUtils {
* These are the apps subject to the hiding/showing logic in
* {@link CarrierAppUtils#disableCarrierAppsUntilPrivileged(String, IPackageManager,
* TelephonyManager, int)}, as well as the apps which should have default permissions granted,
- * when a matching SIM is inserted.
+ * when a matching SIM is inserted. Additionally, all permanently enabled system carrier
+ * apps are included in the returned list.
*
* Whether or not the app is actually considered a default app depends on whether the app has
* carrier privileges as determined by the SIMs in the device.
@@ -177,20 +209,26 @@ public final class CarrierAppUtils {
IPackageManager packageManager, int userId) {
String[] systemCarrierAppsDisabledUntilUsed = Resources.getSystem().getStringArray(
com.android.internal.R.array.config_disabledUntilUsedPreinstalledCarrierApps);
+ String[] systemCarrierAppsEnabled = Resources.getSystem().getStringArray(
+ com.android.internal.R.array.config_enabledPreinstalledCarrierApps);
return getDefaultCarrierAppCandidatesHelper(packageManager, userId,
- systemCarrierAppsDisabledUntilUsed);
+ systemCarrierAppsDisabledUntilUsed, systemCarrierAppsEnabled);
}
private static List<ApplicationInfo> getDefaultCarrierAppCandidatesHelper(
IPackageManager packageManager, int userId,
- String[] systemCarrierAppsDisabledUntilUsed) {
- if (systemCarrierAppsDisabledUntilUsed == null
- || systemCarrierAppsDisabledUntilUsed.length == 0) {
+ String[] systemCarrierAppsDisabledUntilUsed,
+ String[] systemCarrierAppsEnabled) {
+ if ((systemCarrierAppsDisabledUntilUsed == null
+ || systemCarrierAppsDisabledUntilUsed.length == 0)
+ && (systemCarrierAppsEnabled == null
+ || systemCarrierAppsEnabled.length == 0)) {
return null;
}
List<ApplicationInfo> apps = null;
try {
- apps = new ArrayList<>(systemCarrierAppsDisabledUntilUsed.length);
+ apps = new ArrayList<>(systemCarrierAppsDisabledUntilUsed.length
+ + systemCarrierAppsEnabled.length);
for (String packageName : systemCarrierAppsDisabledUntilUsed) {
ApplicationInfo ai = packageManager.getApplicationInfo(packageName,
PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS, userId);
@@ -203,6 +241,13 @@ public final class CarrierAppUtils {
}
apps.add(ai);
}
+
+ for (String carrierApp : systemCarrierAppsEnabled) {
+ ApplicationInfo ai = packageManager.getApplicationInfo(carrierApp, 0, userId);
+ if (ai != null) {
+ apps.add(ai);
+ }
+ }
} catch (RemoteException e) {
Slog.w(TAG, "Could not reach PackageManager", e);
}
diff --git a/src/java/com/android/internal/telephony/CommandsInterface.java b/src/java/com/android/internal/telephony/CommandsInterface.java
index 63a8fd6d0..596004a2b 100644
--- a/src/java/com/android/internal/telephony/CommandsInterface.java
+++ b/src/java/com/android/internal/telephony/CommandsInterface.java
@@ -1683,6 +1683,12 @@ public interface CommandsInterface {
public int getLteOnCdmaMode();
/**
+ * Return if the current radio is LTE on GSM
+ * @hide
+ */
+ public int getLteOnGsmMode();
+
+ /**
* Request the ISIM application on the UICC to perform the AKA
* challenge/response algorithm for IMS authentication. The nonce string
* and challenge response are Base64 encoded Strings.
@@ -1908,20 +1914,15 @@ public interface CommandsInterface {
/**
* Sets user selected subscription at Modem.
*
- * @param slotId
- * Slot.
* @param appIndex
* Application index in the card.
- * @param subId
- * Indicates subscription 0 or subscription 1.
- * @param subStatus
- * Activation status, 1 = activate and 0 = deactivate.
+ * @param activate
+ * Whether to activate or deactivate the subscription
* @param result
* Callback message contains the information of SUCCESS/FAILURE.
*/
// FIXME Update the doc and consider modifying the request to make more generic.
- public void setUiccSubscription(int slotId, int appIndex, int subId, int subStatus,
- Message result);
+ public void setUiccSubscription(int appIndex, boolean activate, Message result);
/**
* Tells the modem if data is allowed or not.
@@ -2031,4 +2032,10 @@ public interface CommandsInterface {
* @param lchStatus, true if call is in lch state
*/
public void setLocalCallHold(boolean lchStatus);
+
+ /**
+ * @hide
+ * CM-specific: Ask the RIL about the presence of back-compat flags
+ */
+ public boolean needsOldRilFeature(String feature);
}
diff --git a/src/java/com/android/internal/telephony/InboundSmsHandler.java b/src/java/com/android/internal/telephony/InboundSmsHandler.java
index 686ab30ac..29f619fba 100644
--- a/src/java/com/android/internal/telephony/InboundSmsHandler.java
+++ b/src/java/com/android/internal/telephony/InboundSmsHandler.java
@@ -53,6 +53,7 @@ import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.preference.PreferenceManager;
+import android.provider.Settings;
import android.provider.Telephony;
import android.provider.Telephony.Sms.Intents;
import android.service.carrier.CarrierMessagingService;
@@ -69,14 +70,20 @@ import android.text.TextUtils;
import com.android.internal.telephony.uicc.UiccCard;
import com.android.internal.telephony.uicc.UiccController;
+import android.text.TextUtils;
+import com.android.internal.telephony.util.BlacklistUtils;
+import com.android.internal.telephony.PhoneBase;
import com.android.internal.util.HexDump;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
+import java.util.Map;
/**
* This class broadcasts incoming SMS messages to interested apps after storing them in
@@ -542,20 +549,40 @@ public abstract class InboundSmsHandler extends StateMachine {
return;
}
- int result;
+ int result, blacklistMatchType = -1;
+ SmsMessage sms = null;
+
try {
- SmsMessage sms = (SmsMessage) ar.result;
+ sms = (SmsMessage) ar.result;
result = dispatchMessage(sms.mWrappedSmsMessage);
} catch (RuntimeException ex) {
loge("Exception dispatching message", ex);
result = Intents.RESULT_SMS_GENERIC_ERROR;
}
+ // Translate (internal) blacklist check results to
+ // RESULT_SMS_HANDLED + match type
+ switch (result) {
+ case Intents.RESULT_SMS_BLACKLISTED_UNKNOWN:
+ blacklistMatchType = BlacklistUtils.MATCH_UNKNOWN;
+ result = Intents.RESULT_SMS_HANDLED;
+ break;
+ case Intents.RESULT_SMS_BLACKLISTED_LIST:
+ blacklistMatchType = BlacklistUtils.MATCH_LIST;
+ result = Intents.RESULT_SMS_HANDLED;
+ break;
+ case Intents.RESULT_SMS_BLACKLISTED_REGEX:
+ blacklistMatchType = BlacklistUtils.MATCH_REGEX;
+ result = Intents.RESULT_SMS_HANDLED;
+ break;
+ }
+
+
// RESULT_OK means that the SMS will be acknowledged by special handling,
// e.g. for SMS-PP data download. Any other result, we should ack here.
if (result != Activity.RESULT_OK) {
boolean handled = (result == Intents.RESULT_SMS_HANDLED);
- notifyAndAcknowledgeLastIncomingSms(handled, result, null);
+ notifyAndAcknowledgeLastIncomingSms(handled, result, blacklistMatchType, sms, null);
}
}
@@ -649,14 +676,26 @@ public abstract class InboundSmsHandler extends StateMachine {
* and send an acknowledge message to the network.
* @param success indicates that last message was successfully received.
* @param result result code indicating any error
+ * @param blacklistMatchType blacklist type if the message was blacklisted,
+ * -1 if it wasn't blacklisted
+ * @param sms incoming SMS
* @param response callback message sent when operation completes.
*/
void notifyAndAcknowledgeLastIncomingSms(boolean success,
- int result, Message response) {
- if (!success) {
+ int result, int blacklistMatchType, SmsMessage sms, Message response) {
+ if (!success || blacklistMatchType >= 0) {
// broadcast SMS_REJECTED_ACTION intent
Intent intent = new Intent(Intents.SMS_REJECTED_ACTION);
intent.putExtra("result", result);
+ intent.putExtra("blacklisted", blacklistMatchType >= 0);
+ if (blacklistMatchType >= 0) {
+ intent.putExtra("blacklistMatchType", blacklistMatchType);
+ }
+ if (sms != null) {
+ intent.putExtra("sender", sms.getOriginatingAddress());
+ intent.putExtra("timestamp", sms.getTimestampMillis());
+ }
+ if (DBG) log("notifyAndAcknowledgeLastIncomingSms(): reject intent= " + intent);
mContext.sendBroadcast(intent, android.Manifest.permission.RECEIVE_SMS);
}
acknowledgeLastIncomingSms(success, result, response);
@@ -678,6 +717,11 @@ public abstract class InboundSmsHandler extends StateMachine {
* @return {@link Intents#RESULT_SMS_HANDLED} if the message was accepted, or an error status
*/
protected int dispatchNormalMessage(SmsMessageBase sms) {
+ int blacklistResult = checkIfBlacklisted(sms);
+ if (blacklistResult != Intents.RESULT_SMS_HANDLED) {
+ return blacklistResult;
+ }
+
SmsHeader smsHeader = sms.getUserDataHeader();
InboundSmsTracker tracker;
@@ -707,6 +751,22 @@ public abstract class InboundSmsHandler extends StateMachine {
return addTrackerToRawTableAndSendMessage(tracker);
}
+ private int checkIfBlacklisted(SmsMessageBase sms) {
+ int result = BlacklistUtils.isListed(mContext,
+ sms.getOriginatingAddress(), BlacklistUtils.BLOCK_MESSAGES);
+
+ switch (result) {
+ case BlacklistUtils.MATCH_UNKNOWN:
+ return Intents.RESULT_SMS_BLACKLISTED_UNKNOWN;
+ case BlacklistUtils.MATCH_LIST:
+ return Intents.RESULT_SMS_BLACKLISTED_LIST;
+ case BlacklistUtils.MATCH_REGEX:
+ return Intents.RESULT_SMS_BLACKLISTED_REGEX;
+ }
+
+ return Intents.RESULT_SMS_HANDLED;
+ }
+
/**
* Helper to add the tracker to the raw table and then send a message to broadcast it, if
* successful. Returns the SMS intent status to return to the SMSC.
@@ -821,6 +881,22 @@ public abstract class InboundSmsHandler extends StateMachine {
}
}
+ List<String> regAddresses = Settings.Secure.getDelimitedStringAsList(mContext.getContentResolver(),
+ Settings.Secure.PROTECTED_SMS_ADDRESSES , "|");
+
+ List<String> allAddresses = Intents
+ .getNormalizedAddressesFromPdus(pdus, tracker.getFormat());
+
+ if (!Collections.disjoint(regAddresses, allAddresses)) {
+ Intent intent = new Intent(Intents.PROTECTED_SMS_RECEIVED_ACTION);
+ intent.putExtra("pdus", pdus);
+ intent.putExtra("format", tracker.getFormat());
+ Bundle options = handleSmsWhitelisting(intent.getComponent());
+ dispatchIntent(intent, android.Manifest.permission.RECEIVE_PROTECTED_SMS,
+ AppOpsManager.OP_RECEIVE_SMS, options, resultReceiver, UserHandle.OWNER);
+ return true;
+ }
+
List<String> carrierPackages = null;
UiccCard card = UiccController.getInstance().getUiccCard(mPhone.getPhoneId());
if (card != null) {
diff --git a/src/java/com/android/internal/telephony/Phone.java b/src/java/com/android/internal/telephony/Phone.java
index 94c0f349d..1f95d2793 100755
--- a/src/java/com/android/internal/telephony/Phone.java
+++ b/src/java/com/android/internal/telephony/Phone.java
@@ -145,20 +145,18 @@ public interface Phone {
int NT_MODE_LTE_ONLY = RILConstants.NETWORK_MODE_LTE_ONLY;
int NT_MODE_LTE_WCDMA = RILConstants.NETWORK_MODE_LTE_WCDMA;
- int PREFERRED_NT_MODE = RILConstants.PREFERRED_NETWORK_MODE;
+ int NT_MODE_TDSCDMA_ONLY = RILConstants.NETWORK_MODE_TDSCDMA_ONLY;
+ int NT_MODE_TDSCDMA_WCDMA = RILConstants.NETWORK_MODE_TDSCDMA_WCDMA;
+ int NT_MODE_LTE_TDSCDMA = RILConstants.NETWORK_MODE_LTE_TDSCDMA;
+ int NT_MODE_TDSCDMA_GSM = RILConstants.NETWORK_MODE_TDSCDMA_GSM;
+ int NT_MODE_LTE_TDSCDMA_GSM = RILConstants.NETWORK_MODE_LTE_TDSCDMA_GSM;
+ int NT_MODE_TDSCDMA_GSM_WCDMA = RILConstants.NETWORK_MODE_TDSCDMA_GSM_WCDMA;
+ int NT_MODE_LTE_TDSCDMA_WCDMA = RILConstants.NETWORK_MODE_LTE_TDSCDMA_WCDMA;
+ int NT_MODE_LTE_TDSCDMA_GSM_WCDMA = RILConstants.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA;
+ int NT_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA = RILConstants.NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA;
+ int NT_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA = RILConstants.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA;
- int NT_MODE_TD_SCDMA_ONLY = RILConstants.NETWORK_MODE_TD_SCDMA_ONLY;
- int NT_MODE_TD_SCDMA_WCDMA = RILConstants.NETWORK_MODE_TD_SCDMA_WCDMA;
- int NT_MODE_TD_SCDMA_LTE = RILConstants.NETWORK_MODE_TD_SCDMA_LTE;
- int NT_MODE_TD_SCDMA_GSM = RILConstants.NETWORK_MODE_TD_SCDMA_GSM;
- int NT_MODE_TD_SCDMA_GSM_LTE = RILConstants.NETWORK_MODE_TD_SCDMA_GSM_LTE;
- int NT_MODE_TD_SCDMA_GSM_WCDMA = RILConstants.NETWORK_MODE_TD_SCDMA_GSM_WCDMA;
- int NT_MODE_TD_SCDMA_WCDMA_LTE = RILConstants.NETWORK_MODE_TD_SCDMA_WCDMA_LTE;
- int NT_MODE_TD_SCDMA_GSM_WCDMA_LTE = RILConstants.NETWORK_MODE_TD_SCDMA_GSM_WCDMA_LTE;
- int NT_MODE_TD_SCDMA_GSM_WCDMA_CDMA_EVDO =
- RILConstants.NETWORK_MODE_TD_SCDMA_GSM_WCDMA_CDMA_EVDO;
- int NT_MODE_TD_SCDMA_LTE_CDMA_EVDO_GSM_WCDMA =
- RILConstants.NETWORK_MODE_TD_SCDMA_LTE_CDMA_EVDO_GSM_WCDMA;
+ int PREFERRED_NT_MODE = RILConstants.PREFERRED_NETWORK_MODE;
// Used for CDMA roaming mode
static final int CDMA_RM_HOME = 0; // Home Networks only, as defined in PRL
@@ -1824,6 +1822,12 @@ public interface Phone {
public int getLteOnCdmaMode();
/**
+ * Return if the current radio is LTE on GSM
+ * @hide
+ */
+ public int getLteOnGsmMode();
+
+ /**
* TODO: Adding a function for each property is not good.
* A fucntion of type getPhoneProp(propType) where propType is an
* enum of GSM+CDMA+LTE props would be a better approach.
diff --git a/src/java/com/android/internal/telephony/PhoneBase.java b/src/java/com/android/internal/telephony/PhoneBase.java
index 94aa3ba1f..5ecee3afb 100644
--- a/src/java/com/android/internal/telephony/PhoneBase.java
+++ b/src/java/com/android/internal/telephony/PhoneBase.java
@@ -1044,6 +1044,7 @@ public abstract class PhoneBase extends Handler implements Phone {
// send the setting on error
}
}
+
if (doAutomatic) {
// wrap the response message in our own message along with
// an empty string (to indicate automatic selection) for the
@@ -1169,7 +1170,7 @@ public abstract class PhoneBase extends Handler implements Phone {
String numeric = sp.getString(NETWORK_SELECTION_KEY + getSubId(), "");
String name = sp.getString(NETWORK_SELECTION_NAME_KEY + getSubId(), "");
String shrt = sp.getString(NETWORK_SELECTION_SHORT_KEY + getSubId(), "");
- return new OperatorInfo(numeric, name, shrt);
+ return new OperatorInfo(name, shrt, numeric);
}
/**
@@ -2296,6 +2297,22 @@ public abstract class PhoneBase extends Handler implements Phone {
return mCi.getLteOnCdmaMode();
}
+ /**
+ * {@hide}
+ */
+ @Override
+ public int getLteOnGsmMode() {
+ return mCi.getLteOnGsmMode();
+ }
+
+ /**
+ * Sets the SIM voice message waiting indicator records.
+ * @param line GSM Subscriber Profile Number, one-based. Only '1' is supported
+ * @param countWaiting The number of messages waiting, if known. Use
+ * -1 to indicate that an unknown number of
+ * messages are waiting
+ */
+ @Override
public void setVoiceMessageWaiting(int line, int countWaiting) {
// This function should be overridden by class GSMPhone and CDMAPhone.
Rlog.e(LOG_TAG, "Error! This function should never be executed, inactive Phone.");
@@ -2630,10 +2647,22 @@ public abstract class PhoneBase extends Handler implements Phone {
mRadioCapability.set(rc);
if (SubscriptionManager.isValidSubscriptionId(getSubId())) {
+ updatePreferredType();
sendSubscriptionSettings(true);
}
}
+ private void updatePreferredType() {
+ int preferredRaf = getRadioAccessFamily();
+ int userNwType = SubscriptionController.getInstance().getUserNwMode(getPhoneId());
+ if (userNwType != SubscriptionManager.DEFAULT_NW_MODE) {
+ preferredRaf &= RadioAccessFamily.getRafFromNetworkType(userNwType);
+ }
+ int filteredType = RadioAccessFamily.getNetworkTypeFromRaf(preferredRaf);
+ TelephonyManager.putIntAtIndex(mContext.getContentResolver(),
+ Settings.Global.PREFERRED_NETWORK_MODE, getPhoneId(), filteredType);
+ }
+
public void sendSubscriptionSettings(boolean restoreNetworkSelection) {
// Send settings down
int type = PhoneFactory.calculatePreferredNetworkType(mContext, getSubId());
@@ -2724,12 +2753,6 @@ public abstract class PhoneBase extends Handler implements Phone {
return getLocaleFromCarrierProperties(mContext);
}
- /* Validate the given extras if the call is for CS domain or not */
- protected boolean shallDialOnCircuitSwitch(Bundle extras) {
- return (extras != null && extras.getInt(QtiVideoCallConstants.EXTRA_CALL_DOMAIN,
- QtiVideoCallConstants.DOMAIN_AUTOMATIC) == QtiVideoCallConstants.DOMAIN_CS);
- }
-
protected boolean isMatchGid(String gid) {
String gid1 = getGroupIdLevel1();
int gidLength = gid.length();
@@ -2740,6 +2763,12 @@ public abstract class PhoneBase extends Handler implements Phone {
return false;
}
+ /* Validate the given extras if the call is for CS domain or not */
+ protected boolean shallDialOnCircuitSwitch(Bundle extras) {
+ return (extras != null && extras.getInt(QtiVideoCallConstants.EXTRA_CALL_DOMAIN,
+ QtiVideoCallConstants.DOMAIN_AUTOMATIC) == QtiVideoCallConstants.DOMAIN_CS);
+ }
+
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("PhoneBase: subId=" + getSubId());
pw.println(" mPhoneId=" + mPhoneId);
diff --git a/src/java/com/android/internal/telephony/PhoneFactory.java b/src/java/com/android/internal/telephony/PhoneFactory.java
index cb3a17c13..7091a6e74 100644
--- a/src/java/com/android/internal/telephony/PhoneFactory.java
+++ b/src/java/com/android/internal/telephony/PhoneFactory.java
@@ -48,6 +48,7 @@ import com.android.internal.util.IndentingPrintWriter;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.HashMap;
+import java.lang.reflect.Constructor;
/**
* {@hide}
@@ -124,6 +125,15 @@ public class PhoneFactory {
sPhoneNotifier = new DefaultPhoneNotifier();
+ // Get preferred network mode
+ int preferredNetworkMode = RILConstants.PREFERRED_NETWORK_MODE;
+ if (TelephonyManager.getLteOnCdmaModeStatic() == PhoneConstants.LTE_ON_CDMA_TRUE) {
+ preferredNetworkMode = Phone.NT_MODE_GLOBAL;
+ }
+ if (TelephonyManager.getLteOnGsmModeStatic() != 0) {
+ preferredNetworkMode = Phone.NT_MODE_LTE_GSM_WCDMA;
+ }
+
int cdmaSubscription = CdmaSubscriptionSourceManager.getDefault(context);
Rlog.i(LOG_TAG, "Cdma Subscription set to " + cdmaSubscription);
@@ -134,6 +144,8 @@ public class PhoneFactory {
int[] networkModes = new int[numPhones];
sProxyPhones = new PhoneProxy[numPhones];
sCommandsInterfaces = new RIL[numPhones];
+ String sRILClassname = SystemProperties.get("ro.telephony.ril_class", "RIL").trim();
+ Rlog.i(LOG_TAG, "RILClassname is " + sRILClassname);
for (int i = 0; i < numPhones; i++) {
// reads the system properties and makes commandsinterface
@@ -145,11 +157,23 @@ public class PhoneFactory {
} catch (SettingNotFoundException snfe) {
Rlog.e(LOG_TAG, "Settings Exception Reading Value At Index for"+
" Settings.Global.PREFERRED_NETWORK_MODE");
- networkModes[i] = RILConstants.PREFERRED_NETWORK_MODE;
+ networkModes[i] = preferredNetworkMode;
}
Rlog.i(LOG_TAG, "Network Mode set to " + Integer.toString(networkModes[i]));
- sCommandsInterfaces[i] = new RIL(context, networkModes[i],
- cdmaSubscription, i);
+ // Use reflection to construct the RIL class (defaults to RIL)
+ try {
+ sCommandsInterfaces[i] = instantiateCustomRIL(
+ sRILClassname, context, networkModes[i], cdmaSubscription, i);
+ } catch (Exception e) {
+ // 6 different types of exceptions are thrown here that it's
+ // easier to just catch Exception as our "error handling" is the same.
+ // Yes, we're blocking the whole thing and making the radio unusable. That's by design.
+ // The log message should make it clear why the radio is broken
+ while (true) {
+ Rlog.e(LOG_TAG, "Unable to construct custom RIL class", e);
+ try {Thread.sleep(10000);} catch (InterruptedException ie) {}
+ }
+ }
}
Rlog.i(LOG_TAG, "Creating SubscriptionController");
TelephonyPluginDelegate.getInstance().initSubscriptionController(context,
@@ -209,6 +233,13 @@ public class PhoneFactory {
// because ImsService might need it when it is being opened.
for (int i = 0; i < numPhones; i++) {
sProxyPhones[i].startMonitoringImsService();
+ // Get users NW type, let it override if its not the default NW mode (-1)
+ int userNwType = SubscriptionController.getInstance().getUserNwMode(
+ sProxyPhones[i].getSubId());
+ if (userNwType != SubscriptionManager.DEFAULT_NW_MODE
+ && userNwType != networkModes[i]) {
+ sProxyPhones[i].setPreferredNetworkType(userNwType, null);
+ }
}
}
}
@@ -231,6 +262,14 @@ public class PhoneFactory {
}
}
+ private static <T> T instantiateCustomRIL(
+ String sRILClassname, Context context, int networkMode, int cdmaSubscription, Integer instanceId)
+ throws Exception {
+ Class<?> clazz = Class.forName("com.android.internal.telephony." + sRILClassname);
+ Constructor<?> constructor = clazz.getConstructor(Context.class, int.class, int.class, Integer.class);
+ return (T) clazz.cast(constructor.newInstance(context, networkMode, cdmaSubscription, instanceId));
+ }
+
public static Phone getDefaultPhone() {
synchronized (sLockProxyPhones) {
if (!sMadeDefaults) {
@@ -338,6 +377,14 @@ public class PhoneFactory {
networkType = android.provider.Settings.Global.getInt(context.getContentResolver(),
android.provider.Settings.Global.PREFERRED_NETWORK_MODE + phoneSubId,
phoneIdNetworkType);
+
+ // Get users NW type, let it override if its not the default NW mode (-1)
+ int userNwType = SubscriptionController.getInstance().getUserNwMode(phoneSubId);
+ if (userNwType != SubscriptionManager.DEFAULT_NW_MODE && userNwType != networkType) {
+ Rlog.d(LOG_TAG, "calculatePreferredNetworkType: overriding for usernw mode " +
+ "phoneSubId = " + phoneSubId + " networkType = " + networkType);
+ networkType = userNwType;
+ }
} else {
Rlog.d(LOG_TAG, "calculatePreferredNetworkType: phoneSubId = " + phoneSubId +
" is not a active SubId");
@@ -555,4 +602,8 @@ public class PhoneFactory {
ipw.flush();
}
}
+
+ public static SubscriptionInfoUpdater getSubscriptionInfoUpdater() {
+ return sSubInfoRecordUpdater;
+ }
}
diff --git a/src/java/com/android/internal/telephony/PhoneProxy.java b/src/java/com/android/internal/telephony/PhoneProxy.java
index 67a14006d..e8a3e202a 100644
--- a/src/java/com/android/internal/telephony/PhoneProxy.java
+++ b/src/java/com/android/internal/telephony/PhoneProxy.java
@@ -1373,6 +1373,14 @@ public class PhoneProxy extends Handler implements Phone {
return mActivePhone.getLteOnCdmaMode();
}
+ /**
+ * {@hide}
+ */
+ @Override
+ public int getLteOnGsmMode() {
+ return mActivePhone.getLteOnGsmMode();
+ }
+
@Override
public void setVoiceMessageWaiting(int line, int countWaiting) {
mActivePhone.setVoiceMessageWaiting(line, countWaiting);
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index 8e40294d5..59d0e00b0 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -32,6 +32,7 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.res.Resources;
import android.hardware.display.DisplayManager;
import android.net.ConnectivityManager;
import android.net.LocalSocket;
@@ -233,7 +234,7 @@ class RILRequest {
*
* {@hide}
*/
-public final class RIL extends BaseCommands implements CommandsInterface {
+public class RIL extends BaseCommands implements CommandsInterface {
static final String RILJ_LOG_TAG = "RILJ";
static final boolean RILJ_LOGD = true;
static final boolean RILJ_LOGV = false; // STOPSHIP if true
@@ -283,7 +284,12 @@ public final class RIL extends BaseCommands implements CommandsInterface {
// When we are testing emergency calls
AtomicBoolean mTestingEmergencyCall = new AtomicBoolean(false);
- private Integer mInstanceId;
+ protected Integer mInstanceId;
+
+ // Number of per-network elements expected in QUERY_AVAILABLE_NETWORKS's response.
+ // 4 elements is default, but many RILs actually return 5, making it impossible to
+ // divide the response array without prior knowledge of the number of elements.
+ protected int mQANElements = SystemProperties.getInt("ro.ril.telephony.mqanelements", 4);
//***** Events
@@ -521,10 +527,10 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return messageLength;
}
- class RILReceiver implements Runnable {
+ protected class RILReceiver implements Runnable {
byte[] buffer;
- RILReceiver() {
+ protected RILReceiver() {
buffer = new byte[RIL_MAX_COMMAND_BYTES];
}
@@ -587,6 +593,20 @@ public final class RIL extends BaseCommands implements CommandsInterface {
Rlog.i(RILJ_LOG_TAG, "(" + mInstanceId + ") Connected to '"
+ rilSocket + "' socket");
+ /* Compatibility with qcom's DSDS (Dual SIM) stack */
+ if (needsOldRilFeature("qcomdsds")) {
+ String str = "SUB1";
+ byte[] data = str.getBytes();
+ try {
+ mSocket.getOutputStream().write(data);
+ Rlog.i(RILJ_LOG_TAG, "Data sent!!");
+ } catch (IOException ex) {
+ Rlog.e(RILJ_LOG_TAG, "IOException", ex);
+ } catch (RuntimeException exc) {
+ Rlog.e(RILJ_LOG_TAG, "Uncaught exception ", exc);
+ }
+ }
+
int length = 0;
try {
InputStream is = mSocket.getInputStream();
@@ -683,7 +703,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
riljLog("Not starting RILReceiver: wifi-only");
} else {
riljLog("Starting RILReceiver" + mInstanceId);
- mReceiver = new RILReceiver();
+ mReceiver = createRILReceiver();
mReceiverThread = new Thread(mReceiver, "RILReceiver" + mInstanceId);
mReceiverThread.start();
@@ -705,6 +725,10 @@ public final class RIL extends BaseCommands implements CommandsInterface {
tdc.registerRIL(this);
}
+ protected RILReceiver createRILReceiver() {
+ return new RILReceiver();
+ }
+
//***** CommandsInterface implementation
@Override
@@ -750,19 +774,17 @@ public final class RIL extends BaseCommands implements CommandsInterface {
send(rr);
}
- public void setUiccSubscription(int slotId, int appIndex, int subId,
- int subStatus, Message result) {
+ public void setUiccSubscription(int appIndex, boolean activate, Message result) {
//Note: This RIL request is also valid for SIM and RUIM (ICC card)
RILRequest rr = RILRequest.obtain(RIL_REQUEST_SET_UICC_SUBSCRIPTION, result);
if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
- + " slot: " + slotId + " appIndex: " + appIndex
- + " subId: " + subId + " subStatus: " + subStatus);
+ + " appIndex: " + appIndex + " activate: " + activate);
- rr.mParcel.writeInt(slotId);
+ rr.mParcel.writeInt(mInstanceId);
rr.mParcel.writeInt(appIndex);
- rr.mParcel.writeInt(subId);
- rr.mParcel.writeInt(subStatus);
+ rr.mParcel.writeInt(mInstanceId);
+ rr.mParcel.writeInt(activate ? 1 : 0);
send(rr);
}
@@ -793,9 +815,13 @@ public final class RIL extends BaseCommands implements CommandsInterface {
if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
- rr.mParcel.writeInt(2);
+ boolean oldRil = needsOldRilFeature("facilitylock");
+
+ rr.mParcel.writeInt(oldRil ? 1 : 2);
rr.mParcel.writeString(pin);
- rr.mParcel.writeString(aid);
+
+ if (!oldRil)
+ rr.mParcel.writeString(aid);
send(rr);
}
@@ -813,10 +839,14 @@ public final class RIL extends BaseCommands implements CommandsInterface {
if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
- rr.mParcel.writeInt(3);
+ boolean oldRil = needsOldRilFeature("facilitylock");
+
+ rr.mParcel.writeInt(oldRil ? 2 : 3);
rr.mParcel.writeString(puk);
rr.mParcel.writeString(newPin);
- rr.mParcel.writeString(aid);
+
+ if (!oldRil)
+ rr.mParcel.writeString(aid);
send(rr);
}
@@ -834,9 +864,13 @@ public final class RIL extends BaseCommands implements CommandsInterface {
if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
- rr.mParcel.writeInt(2);
+ boolean oldRil = needsOldRilFeature("facilitylock");
+
+ rr.mParcel.writeInt(oldRil ? 1 : 2);
rr.mParcel.writeString(pin);
- rr.mParcel.writeString(aid);
+
+ if (!oldRil)
+ rr.mParcel.writeString(aid);
send(rr);
}
@@ -854,10 +888,14 @@ public final class RIL extends BaseCommands implements CommandsInterface {
if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
- rr.mParcel.writeInt(3);
+ boolean oldRil = needsOldRilFeature("facilitylock");
+
+ rr.mParcel.writeInt(oldRil ? 2 : 3);
rr.mParcel.writeString(puk);
rr.mParcel.writeString(newPin2);
- rr.mParcel.writeString(aid);
+
+ if (!oldRil)
+ rr.mParcel.writeString(aid);
send(rr);
}
@@ -875,10 +913,14 @@ public final class RIL extends BaseCommands implements CommandsInterface {
if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
- rr.mParcel.writeInt(3);
+ boolean oldRil = needsOldRilFeature("facilitylock");
+
+ rr.mParcel.writeInt(oldRil ? 2 : 3);
rr.mParcel.writeString(oldPin);
rr.mParcel.writeString(newPin);
- rr.mParcel.writeString(aid);
+
+ if (!oldRil)
+ rr.mParcel.writeString(aid);
send(rr);
}
@@ -896,10 +938,14 @@ public final class RIL extends BaseCommands implements CommandsInterface {
if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
- rr.mParcel.writeInt(3);
+ boolean oldRil = needsOldRilFeature("facilitylock");
+
+ rr.mParcel.writeInt(oldRil ? 2 : 3);
rr.mParcel.writeString(oldPin2);
rr.mParcel.writeString(newPin2);
- rr.mParcel.writeString(aid);
+
+ if (!oldRil)
+ rr.mParcel.writeString(aid);
send(rr);
}
@@ -1014,8 +1060,16 @@ public final class RIL extends BaseCommands implements CommandsInterface {
getIMSIForApp(String aid, Message result) {
RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_IMSI, result);
- rr.mParcel.writeInt(1);
- rr.mParcel.writeString(aid);
+ boolean skipNullAid = needsOldRilFeature("skipnullaid");
+ boolean writeAidOnly = needsOldRilFeature("writeaidonly");
+
+ if (!writeAidOnly && (aid != null || !skipNullAid)) {
+ rr.mParcel.writeInt(1);
+ rr.mParcel.writeString(aid);
+ }
+
+ if (writeAidOnly)
+ rr.mParcel.writeString(aid);
if (RILJ_LOGD) riljLog(rr.serialString() +
"> getIMSI: " + requestToString(rr.mRequest)
@@ -1513,7 +1567,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
response);
rr.mParcel.writeInt(status);
- rr.mParcel.writeString(pdu);
+ constructCdmaWriteSmsRilRequest(rr, IccUtils.hexStringToBytes(pdu));
if (RILJ_LOGV) riljLog(rr.serialString() + "> "
+ requestToString(rr.mRequest)
@@ -1523,6 +1577,98 @@ public final class RIL extends BaseCommands implements CommandsInterface {
}
/**
+ * Restructures PDU data so that it is consistent with RIL
+ * data structure.
+ *
+ * @param pdu The data to be written to the RUIM card.
+ */
+ private void constructCdmaWriteSmsRilRequest(RILRequest rr, byte[] pdu) {
+ int address_nbr_of_digits;
+ int subaddr_nbr_of_digits;
+ int bearerDataLength;
+ ByteArrayInputStream bais = new ByteArrayInputStream(pdu);
+ DataInputStream dis = new DataInputStream(bais);
+
+ try {
+ int teleServiceId = 0;
+ byte servicePresent = 0;
+ int serviceCategory = 0;
+
+ int address_digit_mode = 0;
+ int address_nbr_mode = 0;
+ int address_ton = 0;
+ int address_nbr_plan = 0;
+
+ int subaddressType = 0;
+ byte subaddr_odd = 0;
+
+ teleServiceId = dis.readInt();
+ rr.mParcel.writeInt(teleServiceId);
+ servicePresent = (byte) dis.readInt();
+ rr.mParcel.writeByte(servicePresent);
+ serviceCategory = dis.readInt();
+ rr.mParcel.writeInt(serviceCategory);
+
+ address_digit_mode = dis.readByte();
+ rr.mParcel.writeInt(address_digit_mode);
+ address_nbr_mode = dis.readByte();
+ rr.mParcel.writeInt(address_nbr_mode);
+ address_ton = dis.readByte();
+ rr.mParcel.writeInt(address_ton);
+ address_nbr_plan = dis.readByte();
+ rr.mParcel.writeInt(address_nbr_plan);
+
+ address_nbr_of_digits = dis.readByte();
+ rr.mParcel.writeByte((byte) address_nbr_of_digits);
+ for (int i = 0; i < address_nbr_of_digits; i++) {
+ rr.mParcel.writeByte(dis.readByte()); // address_orig_bytes[i]
+ }
+
+ // int
+ subaddressType = dis.readByte();
+ rr.mParcel.writeInt(subaddressType); // subaddressType
+ subaddr_odd = (byte) dis.readByte();
+ rr.mParcel.writeByte(subaddr_odd); // subaddr_odd
+ subaddr_nbr_of_digits = (byte) dis.readByte();
+ rr.mParcel.writeByte((byte) subaddr_nbr_of_digits);
+ for (int i = 0; i < subaddr_nbr_of_digits; i++) {
+ rr.mParcel.writeByte(dis.readByte()); // subaddr_orig_bytes[i]
+ }
+
+ bearerDataLength = dis.readByte() & 0xff;
+ rr.mParcel.writeInt(bearerDataLength);
+ for (int i = 0; i < bearerDataLength; i++) {
+ rr.mParcel.writeByte(dis.readByte()); // bearerData[i]
+ }
+
+ riljLog(" teleServiceId=" + teleServiceId + " servicePresent=" + servicePresent
+ + " serviceCategory=" + serviceCategory
+ + " address_digit_mode=" + address_digit_mode
+ + " address_nbr_mode=" + address_nbr_mode + " address_ton=" + address_ton
+ + " address_nbr_plan=" + address_nbr_plan
+ + " address_nbr_of_digits=" + address_nbr_of_digits
+ + " subaddressType=" + subaddressType + " subaddr_odd= " + subaddr_odd
+ + " subaddr_nbr_of_digits=" + subaddr_nbr_of_digits
+ + " bearerDataLength=" + bearerDataLength);
+ } catch (IOException ex) {
+ if (RILJ_LOGD) riljLog("sendSmsCdma: conversion from input stream to object failed: "
+ + ex);
+ } finally {
+ try {
+ if (null != bais) {
+ bais.close();
+ }
+
+ if (null != dis) {
+ dis.close();
+ }
+ } catch (IOException e) {
+ if (RILJ_LOGD) riljLog("sendSmsCdma: close input stream exception" + e);
+ }
+ }
+ }
+
+ /**
* Translates EF_SMS status bits to a status value compatible with
* SMS AT commands. See TS 27.005 3.1.
*/
@@ -1896,18 +2042,20 @@ public final class RIL extends BaseCommands implements CommandsInterface {
Message response) {
RILRequest rr = RILRequest.obtain(RIL_REQUEST_QUERY_FACILITY_LOCK, response);
- if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
- + " [" + facility + " " + serviceClass
- + " " + appId + "]");
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+
+ boolean oldRil = needsOldRilFeature("facilitylock");
// count strings
- rr.mParcel.writeInt(4);
+ rr.mParcel.writeInt(oldRil ? 3 : 4);
rr.mParcel.writeString(facility);
rr.mParcel.writeString(password);
rr.mParcel.writeString(Integer.toString(serviceClass));
- rr.mParcel.writeString(appId);
+
+ if (!oldRil)
+ rr.mParcel.writeString(appId);
send(rr);
}
@@ -1931,15 +2079,19 @@ public final class RIL extends BaseCommands implements CommandsInterface {
+ " [" + facility + " " + lockState
+ " " + serviceClass + " " + appId + "]");
+ boolean oldRil = needsOldRilFeature("facilitylock");
+
// count strings
- rr.mParcel.writeInt(5);
+ rr.mParcel.writeInt(oldRil ? 4 : 5);
rr.mParcel.writeString(facility);
lockString = (lockState)?"1":"0";
rr.mParcel.writeString(lockString);
rr.mParcel.writeString(password);
rr.mParcel.writeString(Integer.toString(serviceClass));
- rr.mParcel.writeString(appId);
+
+ if (!oldRil)
+ rr.mParcel.writeString(appId);
send(rr);
@@ -2340,7 +2492,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
}
}
- private void sendScreenState(boolean on) {
+ protected void sendScreenState(boolean on) {
RILRequest rr = RILRequest.obtain(RIL_REQUEST_SCREEN_STATE, null);
rr.mParcel.writeInt(1);
rr.mParcel.writeInt(on ? 1 : 0);
@@ -2359,13 +2511,21 @@ public final class RIL extends BaseCommands implements CommandsInterface {
updateScreenState();
}
- private RadioState getRadioStateFromInt(int stateInt) {
+ protected RadioState getRadioStateFromInt(int stateInt) {
RadioState state;
/* RIL_RadioState ril.h */
switch(stateInt) {
case 0: state = RadioState.RADIO_OFF; break;
case 1: state = RadioState.RADIO_UNAVAILABLE; break;
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
case 10: state = RadioState.RADIO_ON; break;
default:
@@ -2375,7 +2535,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return state;
}
- private void switchToRadioState(RadioState newState) {
+ protected void switchToRadioState(RadioState newState) {
setRadioState(newState);
}
@@ -2426,7 +2586,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
}
}
- private void
+ protected void
send(RILRequest rr) {
Message msg;
@@ -2443,7 +2603,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
msg.sendToTarget();
}
- private void
+ protected void
processResponse (Parcel p) {
int type;
@@ -2465,7 +2625,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
* @param error is the RIL_Errno sent back
* @param loggable true means to print all requests in mRequestList
*/
- private void clearRequestList(int error, boolean loggable) {
+ protected void clearRequestList(int error, boolean loggable) {
RILRequest rr;
synchronized (mRequestList) {
int count = mRequestList.size();
@@ -2489,7 +2649,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
}
}
- private RILRequest findAndRemoveRequestFromList(int serial) {
+ protected RILRequest findAndRemoveRequestFromList(int serial) {
RILRequest rr = null;
synchronized (mRequestList) {
rr = mRequestList.get(serial);
@@ -2501,7 +2661,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return rr;
}
- private RILRequest
+ protected RILRequest
processSolicited (Parcel p) {
int serial, error;
boolean found = false;
@@ -2764,7 +2924,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return rr;
}
- private RadioCapability makeStaticRadioCapability() {
+ protected RadioCapability makeStaticRadioCapability() {
// default to UNKNOWN so we fail fast.
int raf = RadioAccessFamily.RAF_UNKNOWN;
@@ -2863,7 +3023,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return s;
}
- private void
+ protected void
processUnsolicited (Parcel p) {
int response;
Object ret;
@@ -3054,6 +3214,10 @@ public final class RIL extends BaseCommands implements CommandsInterface {
case RIL_UNSOL_DATA_CALL_LIST_CHANGED:
if (RILJ_LOGD) unsljLogRet(response, ret);
+ boolean oldRil = needsOldRilFeature("skipbrokendatacall");
+ if (oldRil && "IP".equals(((ArrayList<DataCallResponse>)ret).get(0).type))
+ break;
+
mDataNetworkStateRegistrants.notifyRegistrants(new AsyncResult(null, ret, null));
break;
@@ -3359,7 +3523,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
*
* @param rilVer is the version of the ril or -1 if disconnected.
*/
- private void notifyRegistrantsRilConnectionChanged(int rilVer) {
+ protected void notifyRegistrantsRilConnectionChanged(int rilVer) {
mRilVersion = rilVer;
if (mRilConnectedRegistrants != null) {
mRilConnectedRegistrants.notifyRegistrants(
@@ -3367,7 +3531,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
}
}
- private Object
+ protected Object
responseInts(Parcel p) {
int numInts;
int response[];
@@ -3383,7 +3547,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return response;
}
- private Object
+ protected Object
responseFailCause(Parcel p) {
LastCallFailCause failCause = new LastCallFailCause();
failCause.causeCode = p.readInt();
@@ -3393,12 +3557,12 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return failCause;
}
- private Object
+ protected Object
responseVoid(Parcel p) {
return null;
}
- private Object
+ protected Object
responseCallForward(Parcel p) {
int numInfos;
CallForwardInfo infos[];
@@ -3421,7 +3585,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return infos;
}
- private Object
+ protected Object
responseSuppServiceNotification(Parcel p) {
SuppServiceNotification notification = new SuppServiceNotification();
@@ -3434,7 +3598,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return notification;
}
- private Object
+ protected Object
responseCdmaSms(Parcel p) {
SmsMessage sms;
sms = SmsMessage.newFromParcel(p);
@@ -3442,7 +3606,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return sms;
}
- private Object
+ protected Object
responseString(Parcel p) {
String response;
@@ -3451,7 +3615,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return response;
}
- private Object
+ protected Object
responseStrings(Parcel p) {
int num;
String response[];
@@ -3461,7 +3625,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return response;
}
- private Object
+ protected Object
responseRaw(Parcel p) {
int num;
byte response[];
@@ -3471,7 +3635,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return response;
}
- private Object
+ protected Object
responseSMS(Parcel p) {
int messageRef, errorCode;
String ackPDU;
@@ -3486,7 +3650,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
}
- private Object
+ protected Object
responseICC_IO(Parcel p) {
int sw1, sw2;
Message ret;
@@ -3504,7 +3668,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return new IccIoResult(sw1, sw2, s);
}
- private Object
+ protected Object
responseICC_IOBase64(Parcel p) {
int sw1, sw2;
Message ret;
@@ -3523,16 +3687,31 @@ public final class RIL extends BaseCommands implements CommandsInterface {
? android.util.Base64.decode(s, android.util.Base64.DEFAULT) : (byte[]) null);
}
- private Object
+ @Override
+ public boolean needsOldRilFeature(String feature) {
+ String[] features = SystemProperties.get("ro.telephony.ril.config", "").split(",");
+ for (String found: features) {
+ if (found.equals(feature))
+ return true;
+ }
+ return false;
+ }
+
+ protected Object
responseIccCardStatus(Parcel p) {
IccCardApplicationStatus appStatus;
+ boolean oldRil = needsOldRilFeature("icccardstatus");
+
IccCardStatus cardStatus = new IccCardStatus();
cardStatus.setCardState(p.readInt());
cardStatus.setUniversalPinState(p.readInt());
cardStatus.mGsmUmtsSubscriptionAppIndex = p.readInt();
cardStatus.mCdmaSubscriptionAppIndex = p.readInt();
- cardStatus.mImsSubscriptionAppIndex = p.readInt();
+
+ if (!oldRil)
+ cardStatus.mImsSubscriptionAppIndex = p.readInt();
+
int numApplications = p.readInt();
// limit to maximum allowed applications
@@ -3540,6 +3719,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
numApplications = IccCardStatus.CARD_MAX_APPS;
}
cardStatus.mApplications = new IccCardApplicationStatus[numApplications];
+
for (int i = 0 ; i < numApplications ; i++) {
appStatus = new IccCardApplicationStatus();
appStatus.app_type = appStatus.AppTypeFromRILInt(p.readInt());
@@ -3555,7 +3735,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return cardStatus;
}
- private Object
+ protected Object
responseSimRefresh(Parcel p) {
IccRefreshResponse response = new IccRefreshResponse();
@@ -3565,7 +3745,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return response;
}
- private Object
+ protected Object
responseCallList(Parcel p) {
int num;
int voiceSettings;
@@ -3643,7 +3823,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return response;
}
- private DataCallResponse getDataCallResponse(Parcel p, int version) {
+ protected DataCallResponse getDataCallResponse(Parcel p, int version) {
DataCallResponse dataCall = new DataCallResponse();
dataCall.version = version;
@@ -3651,13 +3831,21 @@ public final class RIL extends BaseCommands implements CommandsInterface {
dataCall.cid = p.readInt();
dataCall.active = p.readInt();
dataCall.type = p.readString();
+ if (version < 4 || needsOldRilFeature("datacallapn")) {
+ p.readString(); // APN - not used
+ }
String addresses = p.readString();
if (!TextUtils.isEmpty(addresses)) {
dataCall.addresses = addresses.split(" ");
}
+ // DataCallState needs an ifname. Since we don't have one use the name from the ThrottleService resource (default=rmnet0).
+ dataCall.ifname = Resources.getSystem().getString(com.android.internal.R.string.config_datause_iface);
} else {
dataCall.status = p.readInt();
- dataCall.suggestedRetryTime = p.readInt();
+ if (needsOldRilFeature("usehcradio"))
+ dataCall.suggestedRetryTime = -1;
+ else
+ dataCall.suggestedRetryTime = p.readInt();
dataCall.cid = p.readInt();
dataCall.active = p.readInt();
dataCall.type = p.readString();
@@ -3691,11 +3879,11 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return dataCall;
}
- private Object
+ protected Object
responseDataCallList(Parcel p) {
ArrayList<DataCallResponse> response;
-
- int ver = p.readInt();
+ boolean oldRil = needsOldRilFeature("datacall");
+ int ver = (oldRil ? 3 : p.readInt());
int num = p.readInt();
riljLog("responseDataCallList ver=" + ver + " num=" + num);
@@ -3707,9 +3895,10 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return response;
}
- private Object
+ protected Object
responseSetupDataCall(Parcel p) {
- int ver = p.readInt();
+ boolean oldRil = needsOldRilFeature("datacall");
+ int ver = (oldRil ? 3 : p.readInt());
int num = p.readInt();
if (RILJ_LOGV) riljLog("responseSetupDataCall ver=" + ver + " num=" + num);
@@ -3761,20 +3950,20 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return dataCall;
}
- private Object
+ protected Object
responseOperatorInfos(Parcel p) {
String strings[] = (String [])responseStrings(p);
ArrayList<OperatorInfo> ret;
- if (strings.length % 4 != 0) {
+ if (strings.length % mQANElements != 0) {
throw new RuntimeException(
"RIL_REQUEST_QUERY_AVAILABLE_NETWORKS: invalid response. Got "
- + strings.length + " strings, expected multible of 4");
+ + strings.length + " strings, expected multiple of " + mQANElements);
}
- ret = new ArrayList<OperatorInfo>(strings.length / 4);
+ ret = new ArrayList<OperatorInfo>(strings.length / mQANElements);
- for (int i = 0 ; i < strings.length ; i += 4) {
+ for (int i = 0 ; i < strings.length ; i += mQANElements) {
ret.add (
new OperatorInfo(
strings[i+0],
@@ -3786,7 +3975,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return ret;
}
- private Object
+ protected Object
responseCellList(Parcel p) {
int num, rssi;
String location;
@@ -3814,7 +4003,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return response;
}
- private Object responseGetPreferredNetworkType(Parcel p) {
+ protected Object responseGetPreferredNetworkType(Parcel p) {
int [] response = (int[]) responseInts(p);
if (response.length >= 1) {
@@ -3826,7 +4015,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return response;
}
- private Object responseGmsBroadcastConfig(Parcel p) {
+ protected Object responseGmsBroadcastConfig(Parcel p) {
int num;
ArrayList<SmsBroadcastConfigInfo> response;
SmsBroadcastConfigInfo info;
@@ -3848,7 +4037,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return response;
}
- private Object
+ protected Object
responseCdmaBroadcastConfig(Parcel p) {
int numServiceCategories;
int response[];
@@ -3887,7 +4076,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return response;
}
- private Object
+ protected Object
responseSignalStrength(Parcel p) {
// Assume this is gsm, but doesn't matter as ServiceStateTracker
// sets the proper value.
@@ -3895,7 +4084,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return signalStrength;
}
- private ArrayList<CdmaInformationRecords>
+ protected ArrayList<CdmaInformationRecords>
responseCdmaInformationRecord(Parcel p) {
int numberOfInfoRecs;
ArrayList<CdmaInformationRecords> response;
@@ -3915,7 +4104,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return response;
}
- private Object
+ protected Object
responseCdmaCallWaiting(Parcel p) {
CdmaCallWaitingNotification notification = new CdmaCallWaitingNotification();
@@ -3934,7 +4123,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return notification;
}
- private Object
+ protected Object
responseCallRing(Parcel p){
char response[] = new char[4];
@@ -3946,7 +4135,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return response;
}
- private void
+ protected void
notifyRegistrantsCdmaInfoRec(CdmaInformationRecords infoRec) {
int response = RIL_UNSOL_CDMA_INFO_REC;
if (infoRec.record instanceof CdmaInformationRecords.CdmaDisplayInfoRec) {
@@ -3994,7 +4183,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
}
}
- private ArrayList<CellInfo> responseCellInfoList(Parcel p) {
+ protected ArrayList<CellInfo> responseCellInfoList(Parcel p) {
int numberOfInfoRecs;
ArrayList<CellInfo> response;
@@ -4013,7 +4202,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return response;
}
- private Object
+ protected Object
responseHardwareConfig(Parcel p) {
int num;
ArrayList<HardwareConfig> response;
@@ -4051,7 +4240,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return response;
}
- private Object
+ protected Object
responseRadioCapability(Parcel p) {
int version = p.readInt();
int session = p.readInt();
@@ -4071,7 +4260,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return rc;
}
- private Object responseLceData(Parcel p) {
+ protected Object responseLceData(Parcel p) {
final ArrayList<Integer> capacityResponse = new ArrayList<Integer>();
final int capacityDownKbps = p.readInt();
final int confidenceLevel = p.readByte();
@@ -4088,7 +4277,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return capacityResponse;
}
- private Object responseLceStatus(Parcel p) {
+ protected Object responseLceStatus(Parcel p) {
final ArrayList<Integer> statusResponse = new ArrayList<Integer>();
final int lceStatus = (int)p.readByte();
final int actualInterval = p.readInt();
@@ -4101,7 +4290,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
return statusResponse;
}
- private Object responseActivityData(Parcel p) {
+ protected Object responseActivityData(Parcel p) {
final int sleepModeTimeMs = p.readInt();
final int idleModeTimeMs = p.readInt();
int [] txModeTimeMs = new int[ModemActivityInfo.TX_POWER_LEVELS];
@@ -4329,29 +4518,29 @@ public final class RIL extends BaseCommands implements CommandsInterface {
}
}
- private void riljLog(String msg) {
+ protected void riljLog(String msg) {
Rlog.d(RILJ_LOG_TAG, msg
+ (mInstanceId != null ? (" [SUB" + mInstanceId + "]") : ""));
}
- private void riljLogv(String msg) {
+ protected void riljLogv(String msg) {
Rlog.v(RILJ_LOG_TAG, msg
+ (mInstanceId != null ? (" [SUB" + mInstanceId + "]") : ""));
}
- private void unsljLog(int response) {
+ protected void unsljLog(int response) {
riljLog("[UNSL]< " + responseToString(response));
}
- private void unsljLogMore(int response, String more) {
+ protected void unsljLogMore(int response, String more) {
riljLog("[UNSL]< " + responseToString(response) + " " + more);
}
- private void unsljLogRet(int response, Object ret) {
+ protected void unsljLogRet(int response, Object ret) {
riljLog("[UNSL]< " + responseToString(response) + " " + retToString(response, ret));
}
- private void unsljLogvRet(int response, Object ret) {
+ protected void unsljLogvRet(int response, Object ret) {
riljLogv("[UNSL]< " + responseToString(response) + " " + retToString(response, ret));
}
@@ -4721,6 +4910,16 @@ public final class RIL extends BaseCommands implements CommandsInterface {
*/
@Override
public void iccOpenLogicalChannel(String AID, Message response) {
+ if(mRilVersion < 10) {
+ if (response != null) {
+ CommandException ex = new CommandException(
+ CommandException.Error.REQUEST_NOT_SUPPORTED);
+ AsyncResult.forMessage(response, null, ex);
+ response.sendToTarget();
+ }
+ return;
+ }
+
RILRequest rr = RILRequest.obtain(RIL_REQUEST_SIM_OPEN_CHANNEL, response);
rr.mParcel.writeString(AID);
@@ -4751,6 +4950,17 @@ public final class RIL extends BaseCommands implements CommandsInterface {
@Override
public void iccTransmitApduLogicalChannel(int channel, int cla, int instruction,
int p1, int p2, int p3, String data, Message response) {
+
+ if(mRilVersion < 10) {
+ if (response != null) {
+ CommandException ex = new CommandException(
+ CommandException.Error.REQUEST_NOT_SUPPORTED);
+ AsyncResult.forMessage(response, null, ex);
+ response.sendToTarget();
+ }
+ return;
+ }
+
if (channel <= 0) {
throw new RuntimeException(
"Invalid channel in iccTransmitApduLogicalChannel: " + channel);
@@ -4790,6 +5000,17 @@ public final class RIL extends BaseCommands implements CommandsInterface {
*/
private void iccTransmitApduHelper(int rilCommand, int channel, int cla,
int instruction, int p1, int p2, int p3, String data, Message response) {
+
+ if(mRilVersion < 10) {
+ if (response != null) {
+ CommandException ex = new CommandException(
+ CommandException.Error.REQUEST_NOT_SUPPORTED);
+ AsyncResult.forMessage(response, null, ex);
+ response.sendToTarget();
+ }
+ return;
+ }
+
RILRequest rr = RILRequest.obtain(rilCommand, response);
rr.mParcel.writeInt(channel);
rr.mParcel.writeInt(cla);
diff --git a/src/java/com/android/internal/telephony/SubscriptionController.java b/src/java/com/android/internal/telephony/SubscriptionController.java
index 7d9a79e85..41b201d6d 100644
--- a/src/java/com/android/internal/telephony/SubscriptionController.java
+++ b/src/java/com/android/internal/telephony/SubscriptionController.java
@@ -33,6 +33,7 @@ import android.os.ServiceManager;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.preference.PreferenceManager;
+import android.provider.BaseColumns;
import android.provider.Settings;
import android.telephony.RadioAccessFamily;
import android.telephony.Rlog;
@@ -288,13 +289,15 @@ public class SubscriptionController extends ISub.Stub {
SubscriptionManager.MNC));
// FIXME: consider stick this into database too
String countryIso = getSubscriptionCountryIso(id);
+ int userNwMode = cursor.getInt(cursor.getColumnIndexOrThrow(
+ SubscriptionManager.USER_NETWORK_MODE));
if (DBG) {
String iccIdToPrint = SubscriptionInfo.givePrintableIccid(iccId);
logd("[getSubInfoRecord] id:" + id + " iccid:" + iccIdToPrint + " simSlotIndex:" + simSlotIndex
+ " displayName:" + displayName + " nameSource:" + nameSource
+ " iconTint:" + iconTint + " dataRoaming:" + dataRoaming
- + " mcc:" + mcc + " mnc:" + mnc + " countIso:" + countryIso);
+ + " mcc:" + mcc + " mnc:" + mnc + " countIso:" + countryIso + " userNwMode:" + userNwMode);
}
// If line1number has been set to a different number, use it instead.
@@ -303,7 +306,7 @@ public class SubscriptionController extends ISub.Stub {
number = line1Number;
}
return new SubscriptionInfo(id, iccId, simSlotIndex, displayName, carrierName,
- nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc, countryIso);
+ nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc, countryIso, userNwMode);
}
/**
@@ -1407,7 +1410,7 @@ public class SubscriptionController extends ISub.Stub {
public void setDefaultDataSubId(int subId) {
enforceModifyPhoneState("setDefaultDataSubId");
String flexMapSupportType =
- SystemProperties.get("persist.radio.flexmap_type", "nw_mode");
+ SystemProperties.get("persist.radio.flexmap_type", "dds");
if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
throw new RuntimeException("setDefaultDataSubId called with DEFAULT_SUB_ID");
@@ -1750,6 +1753,54 @@ public class SubscriptionController extends ISub.Stub {
Binder.restoreCallingIdentity(token);
}
+ @Override
+ public void activateSubId(int subId) {
+ loge("activateSubId: API not supported, subId = " + subId);
+ }
+
+ @Override
+ public void deactivateSubId(int subId) {
+ loge("deactivateSubId: API not supported, subId = " + subId);
+ }
+
+ @Override
+ public int setSubState(int subId, int subStatus) {
+ int result = 0;
+
+ loge("setSubState: API not supported, subId = " + subId + " subStatus = " + subStatus);
+
+ return result;
+ }
+
+ @Override
+ public int getSubState(int subId) {
+ int result = 0;
+
+ loge("getSubState: API not supported, subId = " + subId);
+
+ return result;
+ }
+
+ /* {@hide} */
+ public void setUserNwMode(int subId, int nwMode) {
+ logd("setUserNwMode, nwMode: " + nwMode + " subId: " + subId);
+ ContentValues value = new ContentValues(1);
+ value.put(SubscriptionManager.USER_NETWORK_MODE, nwMode);
+ mContext.getContentResolver().update(SubscriptionManager.CONTENT_URI,
+ value, BaseColumns._ID + "=" + Integer.toString(subId), null);
+ }
+
+ /* {@hide} */
+ public int getUserNwMode(int subId) {
+ SubscriptionInfo subInfo = getActiveSubscriptionInfo(subId, mContext.getOpPackageName());
+ if (subInfo != null) {
+ return subInfo.mUserNwMode;
+ } else {
+ loge("getUserNwMode: invalid subId = " + subId);
+ return SubscriptionManager.DEFAULT_NW_MODE;
+ }
+ }
+
/**
* Store properties associated with SubscriptionInfo in database
* @param subId Subscription Id of Subscription
diff --git a/src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java b/src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java
index b5f04cf1d..bd52d7ea3 100644
--- a/src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java
+++ b/src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java
@@ -34,6 +34,7 @@ import android.os.IRemoteCallback;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.SystemProperties;
import android.os.UserHandle;
import android.preference.PreferenceManager;
import android.provider.Settings;
@@ -62,6 +63,8 @@ public class SubscriptionInfoUpdater extends Handler {
private static final String LOG_TAG = "SubscriptionInfoUpdater";
private static final int PROJECT_SIM_NUM = TelephonyManager.getDefault().getPhoneCount();
+ private static final boolean DBG = false;
+
private static final int EVENT_SIM_LOCKED_QUERY_ICCID_DONE = 1;
private static final int EVENT_GET_NETWORK_SELECTION_MODE_DONE = 2;
private static final int EVENT_SIM_LOADED = 3;
@@ -71,6 +74,7 @@ public class SubscriptionInfoUpdater extends Handler {
private static final int EVENT_SIM_UNKNOWN = 7;
private static final String ICCID_STRING_FOR_NO_SIM = "";
+ private static final String ICCID_STRING_FOR_NV = "DUMMY_NV_ID";
/**
* int[] sInsertSimState maintains all slots' SIM inserted status currently,
* it may contain 4 kinds of values:
@@ -429,37 +433,7 @@ public class SubscriptionInfoUpdater extends Handler {
int storedSubId = sp.getInt(CURR_SUBID + slotId, -1);
if (storedSubId != subId) {
- int networkType = RILConstants.PREFERRED_NETWORK_MODE;
- //Get previous network mode for this slot,
- // to be more relevant instead of default mode
- try {
- networkType = android.provider.Settings.Global.getInt(
- mContext.getContentResolver(),
- Settings.Global.PREFERRED_NETWORK_MODE + subId);
- } catch (SettingNotFoundException snfe) {
-
- logd("Settings Exception reading value at subid for"+
- " Settings.Global.PREFERRED_NETWORK_MODE");
- try {
- networkType = TelephonyManager.getIntAtIndex(
- mContext.getContentResolver(),
- Settings.Global.PREFERRED_NETWORK_MODE, slotId);
- } catch (SettingNotFoundException retrySnfe) {
- Rlog.e(LOG_TAG, "Settings Exception Reading Value At Index for"+
- " Settings.Global.PREFERRED_NETWORK_MODE");
- }
- }
-
- // Set the modem network mode
- mPhone[slotId].setPreferredNetworkType(networkType, null);
- Settings.Global.putInt(mPhone[slotId].getContext().getContentResolver(),
- Settings.Global.PREFERRED_NETWORK_MODE + subId,
- networkType);
-
- // Only support automatic selection mode on SIM change.
- mPhone[slotId].getNetworkSelectionMode(
- obtainMessage(EVENT_GET_NETWORK_SELECTION_MODE_DONE, new Integer(slotId)));
-
+ setDefaultDataSubNetworkType(slotId, subId);
// Update stored subId
SharedPreferences.Editor editor = sp.edit();
editor.putInt(CURR_SUBID + slotId, subId);
@@ -477,6 +451,87 @@ public class SubscriptionInfoUpdater extends Handler {
updateCarrierServices(slotId, IccCardConstants.INTENT_VALUE_ICC_LOADED);
}
+ private void setDefaultDataSubNetworkType(int slotId, int subId) {
+ if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
+ Rlog.e(LOG_TAG, "setDefaultDataSubNetworkType called with DEFAULT_SUB_ID");
+ return;
+ }
+
+ int networkType = RILConstants.PREFERRED_NETWORK_MODE;
+ //Get previous network mode for this slot,
+ //to be more relevant instead of default mode
+ try {
+ networkType = android.provider.Settings.Global.getInt(
+ mContext.getContentResolver(),
+ Settings.Global.PREFERRED_NETWORK_MODE + subId);
+ } catch (SettingNotFoundException snfe) {
+
+ logd("Settings Exception reading value at subid for"+
+ " Settings.Global.PREFERRED_NETWORK_MODE");
+ try {
+ networkType = TelephonyManager.getIntAtIndex(
+ mContext.getContentResolver(),
+ Settings.Global.PREFERRED_NETWORK_MODE, slotId);
+ } catch (SettingNotFoundException retrySnfe) {
+ Rlog.d(LOG_TAG, "Settings Exception Reading Value At Index for"+
+ " Settings.Global.PREFERRED_NETWORK_MODE");
+ }
+ }
+
+ // Get users NW type, let it override if its not the default NW mode (-1)
+ int userNwType = SubscriptionController.getInstance().getUserNwMode(subId);
+ if (userNwType != SubscriptionManager.DEFAULT_NW_MODE && userNwType != networkType) {
+ networkType = userNwType;
+ }
+ boolean isDsds = TelephonyManager.getDefault().getMultiSimConfiguration()
+ == TelephonyManager.MultiSimVariants.DSDS;
+ if (DBG) Rlog.d(LOG_TAG, "[setDefaultDataSubNetworkType] subId=" + subId);
+ if (DBG) Rlog.d(LOG_TAG, "[setDefaultDataSubNetworkType] isDSDS=" + isDsds);
+ boolean isMultiRat = SystemProperties.getBoolean("ro.ril.multi_rat_capable", false);
+
+ if (isDsds && !isMultiRat) {
+ int networkType2 = Phone.NT_MODE_GSM_ONLY; // Hardcoded due to modem limitation
+ int slotId1 = SubscriptionManager.DEFAULT_SIM_SLOT_INDEX;
+ int slotId2 = SubscriptionManager.DEFAULT_SIM_SLOT_INDEX;
+ int subId1 = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
+ int subId2 = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
+ // Since this is DSDS, there are 2 phones
+ for (int targetSlotId = 0; targetSlotId < PROJECT_SIM_NUM; targetSlotId++) {
+ Phone phone = mPhone[targetSlotId];
+ int id = phone.getSubId();
+
+ if (id == subId) {
+ slotId1 = targetSlotId;
+ subId1 = id;
+ if (DBG) Rlog.d(LOG_TAG, "[setDefaultDataSubNetworkType] networkType1: "
+ + networkType + ", slotId1: " + slotId1);
+ } else {
+ subId2 = id;
+ slotId2 = targetSlotId;
+ if (DBG) Rlog.d(LOG_TAG, "[setDefaultDataSubNetworkType] networkType2: "
+ + networkType2 + ", slotId2: " + slotId2);
+ }
+ }
+ setPreferredNwModeForSlot(slotId1, subId1, networkType);
+ setPreferredNwModeForSlot(slotId2, subId2, networkType2);
+ } else {
+ // Set the modem network mode
+ setPreferredNwModeForSlot(slotId, subId, networkType);
+ }
+
+ // Only support automatic selection mode on SIM change.
+ mPhone[slotId].getNetworkSelectionMode(
+ obtainMessage(EVENT_GET_NETWORK_SELECTION_MODE_DONE, new Integer(slotId)));
+ }
+
+ private void setPreferredNwModeForSlot(int slotId, int subId, int networkType) {
+ mPhone[slotId].setPreferredNetworkType(networkType, null);
+ Settings.Global.putInt(mPhone[slotId].getContext().getContentResolver(),
+ Settings.Global.PREFERRED_NETWORK_MODE + subId,
+ networkType);
+ }
+
+
private void updateCarrierServices(int slotId, String simState) {
CarrierConfigManager configManager = (CarrierConfigManager)
mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
@@ -495,6 +550,15 @@ public class SubscriptionInfoUpdater extends Handler {
updateCarrierServices(slotId, IccCardConstants.INTENT_VALUE_ICC_ABSENT);
}
+ public void updateSubIdForNV(int slotId) {
+ mIccId[slotId] = ICCID_STRING_FOR_NV;
+ logd("[updateSubIdForNV]+ Start");
+ if (isAllIccIdQueryDone()) {
+ logd("[updateSubIdForNV]+ updating");
+ updateSubscriptionInfoByIccId();
+ }
+ }
+
/**
* TODO: Simplify more, as no one is interested in what happened
* only what the current list contains.
@@ -633,8 +697,16 @@ public class SubscriptionInfoUpdater extends Handler {
}
}
- // Ensure the modems are mapped correctly
- mSubscriptionManager.setDefaultDataSubId(mSubscriptionManager.getDefaultDataSubId());
+ if (insertedSimCount == 1) {
+ SubscriptionInfo sir = subInfos.get(0);
+ int subId = sir.getSubscriptionId();
+ mSubscriptionManager.setDefaultDataSubId(subId);
+ mSubscriptionManager.setDefaultVoiceSubId(subId);
+ mSubscriptionManager.setDefaultSmsSubId(subId);
+ } else {
+ // Ensure the modems are mapped correctly
+ mSubscriptionManager.setDefaultDataSubId(mSubscriptionManager.getDefaultDataSubId());
+ }
SubscriptionController.getInstance().notifySubscriptionInfoChanged();
logd("updateSubscriptionInfoByIccId:- SsubscriptionInfo update complete");
diff --git a/src/java/com/android/internal/telephony/TelephonyPluginDelegate.java b/src/java/com/android/internal/telephony/TelephonyPluginDelegate.java
index 8f2d3fe9e..76491b5fe 100644
--- a/src/java/com/android/internal/telephony/TelephonyPluginDelegate.java
+++ b/src/java/com/android/internal/telephony/TelephonyPluginDelegate.java
@@ -32,6 +32,7 @@ import android.content.Context;
import android.util.Log;
import android.telephony.Rlog;
+import com.android.internal.telephony.ConfigResourceUtil;
import com.android.internal.telephony.dataconnection.DcTracker;
import com.android.internal.telephony.dataconnection.DctController;
import com.android.internal.telephony.gsm.GSMPhone;
@@ -66,20 +67,26 @@ public class TelephonyPluginDelegate {
public static void init(Context context) {
if (sMe == null) {
- String fullClsName = context.getResources()
- .getString(R.string.telephony_plugin_class_name);
- String libPath = context.getResources().getString(R.string.telephony_plugin_lib_path);
+ try {
+ final String dir = "/system/framework/";
+ String jarName = ConfigResourceUtil.getStringValue(
+ context, "telephony_plugin_jar_name");
- PathClassLoader classLoader = new PathClassLoader(libPath,
- ClassLoader.getSystemClassLoader());
- Rlog.d(LOG_TAG, "classLoader = " + classLoader);
+ String fullClsName = ConfigResourceUtil.getStringValue(context,
+ "telephony_plugin_class_name");
- if (fullClsName == null || fullClsName.length() == 0) {
- Rlog.d(LOG_TAG, "No customized TelephonyPlugin available, fallback to default");
- fullClsName = "com.android.internal.telephony.DefaultTelephonyPlugin";
- }
- Class<?> cls = null;
- try {
+ String libPath = dir + jarName;
+ Rlog.d(LOG_TAG, "Extension = " +fullClsName + "@" + libPath);
+
+ PathClassLoader classLoader = new PathClassLoader(libPath,
+ ClassLoader.getSystemClassLoader());
+ Rlog.d(LOG_TAG, "classLoader = " + classLoader);
+
+ if (fullClsName == null || fullClsName.length() == 0) {
+ Rlog.d(LOG_TAG, "No customized TelephonyPlugin available, fallback to default");
+ fullClsName = "com.android.internal.telephony.DefaultTelephonyPlugin";
+ }
+ Class<?> cls = null;
cls = Class.forName(fullClsName, false, classLoader);
Rlog.d(LOG_TAG, "cls = " + cls);
Constructor custMethod = cls.getConstructor();
diff --git a/src/java/com/android/internal/telephony/UiccSmsController.java b/src/java/com/android/internal/telephony/UiccSmsController.java
index 9ebbc448b..7dd9e5849 100644
--- a/src/java/com/android/internal/telephony/UiccSmsController.java
+++ b/src/java/com/android/internal/telephony/UiccSmsController.java
@@ -391,6 +391,13 @@ public class UiccSmsController extends ISms.Stub {
return PhoneFactory.isSMSPromptEnabled();
}
+ /**
+ * Set SMS prompt property, enabled ornot
+ **/
+ public void setSMSPromptEnabled(boolean bool) {
+ PhoneFactory.setSMSPromptEnabled(bool);
+ }
+
@Override
public void sendStoredText(int subId, String callingPkg, Uri messageUri, String scAddress,
PendingIntent sentIntent, PendingIntent deliveryIntent) throws RemoteException {
diff --git a/src/java/com/android/internal/telephony/cdma/CDMAPhone.java b/src/java/com/android/internal/telephony/cdma/CDMAPhone.java
index 527d4d163..e180cc290 100644
--- a/src/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/src/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -61,11 +61,13 @@ import com.android.internal.telephony.MmiCode;
import com.android.internal.telephony.OperatorInfo;
import com.android.internal.telephony.PhoneBase;
import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.PhoneNotifier;
import com.android.internal.telephony.PhoneProxy;
import com.android.internal.telephony.PhoneSubInfo;
import com.android.internal.telephony.ServiceStateTracker;
import com.android.internal.telephony.SubscriptionController;
+import com.android.internal.telephony.SubscriptionInfoUpdater;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.TelephonyProperties;
import com.android.internal.telephony.UUSInfo;
@@ -456,10 +458,12 @@ public class CDMAPhone extends PhoneBase {
&& ImsManager.isNonTtyOrTtyOnVolteEnabled(mContext)
&& (imsPhone.getServiceState().getState() != ServiceState.STATE_POWER_OFF);
+ boolean useImsForUt = imsPhone != null && imsPhone.isUtEnabled()
+ && dialString.endsWith("#");
+
boolean isUt = PhoneNumberUtils.extractNetworkPortionAlt(PhoneNumberUtils.
stripSeparators(dialString)).endsWith("#");
- boolean useImsForUt = imsPhone != null && imsPhone.isUtEnabled();
if (DBG) {
Rlog.d(LOG_TAG, "imsUseEnabled=" + imsUseEnabled
@@ -1375,6 +1379,10 @@ public class CDMAPhone extends PhoneBase {
log("notifyMessageWaitingChanged");
mNotifier.notifyMessageWaitingChanged(this);
updateVoiceMail();
+ SubscriptionInfoUpdater subscriptionInfoUpdater = PhoneFactory.getSubscriptionInfoUpdater();
+ if (subscriptionInfoUpdater != null) {
+ subscriptionInfoUpdater.updateSubIdForNV(mPhoneId);
+ }
}
break;
diff --git a/src/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java b/src/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
index df3dabc65..fe577275d 100644
--- a/src/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
@@ -455,10 +455,13 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker {
if (hasChanged) {
boolean hasBrandOverride = mUiccController.getUiccCard(getPhoneId()) == null ? false :
(mUiccController.getUiccCard(getPhoneId()).getOperatorBrandOverride() != null);
- if (!hasBrandOverride && (mCi.getRadioState().isOn()) && (mPhone.isEriFileLoaded()) &&
+ boolean forceEriFromXml =
+ SystemProperties.getBoolean("ro.ril.force_eri_from_xml", false);
+ if ((!hasBrandOverride && (mCi.getRadioState().isOn()) && (mPhone.isEriFileLoaded()) &&
(!isRatLte(mSS.getRilVoiceRadioTechnology()) ||
mPhone.getContext().getResources().getBoolean(com.android.internal.R.
- bool.config_LTE_eri_for_network_name))) {
+ bool.config_LTE_eri_for_network_name)) &&
+ !mIsSubscriptionFromRuim) || forceEriFromXml) {
// Only when CDMA is in service, ERI will take effect
String eriText = mSS.getOperatorAlphaLong();
// Now the CDMAPhone sees the new ServiceState so it can get the
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataCallResponse.java b/src/java/com/android/internal/telephony/dataconnection/DataCallResponse.java
index 51adce3c9..ccae8d9f7 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DataCallResponse.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataCallResponse.java
@@ -143,7 +143,7 @@ public class DataCallResponse {
String [] ap = addr.split("/");
if (ap.length == 2) {
addr = ap[0];
- addrPrefixLen = Integer.parseInt(ap[1]);
+ addrPrefixLen = Integer.parseInt(ap[1].replaceAll("[\\D]",""));
} else {
addrPrefixLen = 0;
}
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
index be4159bbe..e4bc64edd 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
@@ -931,6 +931,11 @@ public class DataConnection extends StateMachine {
}
}
mLinkProperties.setTcpBufferSizes(sizes);
+
+ int segments = SystemProperties.getInt("net.tcp.delack." + ratName, 1);
+ mLinkProperties.setTcpDelayedAckSegments(segments);
+ int usercfg = SystemProperties.getInt("net.tcp.usercfg." + ratName, 0);
+ mLinkProperties.setTcpUserCfg(usercfg);
}
private NetworkCapabilities makeNetworkCapabilities() {
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcController.java b/src/java/com/android/internal/telephony/dataconnection/DcController.java
index c3f7df871..543aad2a9 100755
--- a/src/java/com/android/internal/telephony/dataconnection/DcController.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcController.java
@@ -33,6 +33,7 @@ import android.telephony.Rlog;
import com.android.internal.telephony.DctConstants;
import com.android.internal.telephony.PhoneBase;
import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.dataconnection.DataConnection.ConnectionParams;
import com.android.internal.telephony.dataconnection.DataConnection.UpdateLinkPropertyResult;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
@@ -277,7 +278,8 @@ public class DcController extends StateMachine {
if (DBG) log("onDataStateChanged: inactive, add to cleanup list");
apnsToCleanup.addAll(dc.mApnContexts.keySet());
} else {
- for (ApnContext apnContext : dc.mApnContexts.keySet()) {
+ for (ConnectionParams cp : dc.mApnContexts.values()) {
+ ApnContext apnContext = cp.mApnContext;
if (apnContext.isEnabled()) {
if (DBG) {
log("onDataStateChanged: inactive, add to retry list");
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
index dbfab1fdc..23faebd2a 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
@@ -172,6 +172,10 @@ public class DcTracker extends DcTrackerBase {
private boolean mDeregistrationAlarmState = false;
private PendingIntent mImsDeregistrationDelayIntent = null;
+ /** MMS Data Profile Device Override */
+ private static final int MMS_DATA_PROFILE = SystemProperties.getInt(
+ "ro.telephony.mms_data_profile", RILConstants.DATA_PROFILE_DEFAULT);
+
//***** Constructor
public DcTracker(PhoneBase p) {
super(p);
@@ -2362,7 +2366,7 @@ public class DcTracker extends DcTrackerBase {
}
private boolean isNvSubscription() {
- int radioTech = mPhone.getServiceState().getRilDataRadioTechnology();
+ int radioTech = mPhone.getServiceState().getRilVoiceRadioTechnology();
if (mCdmaSsm == null) {
return false;
}
@@ -2937,6 +2941,8 @@ public class DcTracker extends DcTrackerBase {
return RILConstants.DATA_PROFILE_DEFAULT; // DEFAULT for now
} else if (TextUtils.equals(apnType, PhoneConstants.APN_TYPE_DUN)) {
return RILConstants.DATA_PROFILE_TETHERED;
+ } else if (TextUtils.equals(apnType, PhoneConstants.APN_TYPE_MMS)) {
+ return MMS_DATA_PROFILE;
} else {
return RILConstants.DATA_PROFILE_DEFAULT;
}
diff --git a/src/java/com/android/internal/telephony/dataconnection/DctController.java b/src/java/com/android/internal/telephony/dataconnection/DctController.java
index 8e058cabf..a0bfca571 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DctController.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DctController.java
@@ -472,7 +472,8 @@ public class DctController extends Handler {
Iterator<Integer> iterator = mRequestInfos.keySet().iterator();
while (iterator.hasNext()) {
RequestInfo requestInfo = mRequestInfos.get(iterator.next());
- if (requestInfo.executedPhoneId == phoneId) {
+ if ((requestInfo.executedPhoneId == phoneId)
+ || isWithOutSpecifier(requestInfo)) {
onReleaseRequest(requestInfo);
}
}
@@ -541,7 +542,6 @@ public class DctController extends Handler {
}
protected int getTopPriorityRequestPhoneId() {
- RequestInfo retRequestInfo = null;
String topSubId = null;
int priority = -1;
int subId;
@@ -761,7 +761,6 @@ public class DctController extends Handler {
DcTrackerBase dcTracker =((PhoneBase)mPhone).mDcTracker;
String apn = apnForNetworkRequest(networkRequest);
if (dcTracker.isApnSupported(apn)) {
- requestNetwork(networkRequest, dcTracker.getApnPriority(apn), l);
} else {
final String str = "Unsupported APN";
log(str);
diff --git a/src/java/com/android/internal/telephony/gsm/GSMPhone.java b/src/java/com/android/internal/telephony/gsm/GSMPhone.java
index 470c6a4a7..a20054d0b 100644
--- a/src/java/com/android/internal/telephony/gsm/GSMPhone.java
+++ b/src/java/com/android/internal/telephony/gsm/GSMPhone.java
@@ -839,10 +839,12 @@ public class GSMPhone extends PhoneBase {
&& ImsManager.isNonTtyOrTtyOnVolteEnabled(mContext)
&& (imsPhone.getServiceState().getState() != ServiceState.STATE_POWER_OFF);
+ boolean useImsForUt = imsPhone != null && imsPhone.isUtEnabled()
+ && dialString.endsWith("#");
+
boolean isUt = PhoneNumberUtils.extractNetworkPortionAlt(PhoneNumberUtils.
stripSeparators(dialString)).endsWith("#");
- boolean useImsForUt = imsPhone != null && imsPhone.isUtEnabled();
if (LOCAL_DEBUG) {
Rlog.d(LOG_TAG, "imsUseEnabled=" + imsUseEnabled
diff --git a/src/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/src/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
index 5efc0008e..7334f76ab 100644
--- a/src/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
@@ -1831,6 +1831,14 @@ public class GsmServiceStateTracker extends ServiceStateTracker {
if (nitzSubs.length >= 9) {
String tzname = nitzSubs[8].replace('!','/');
zone = TimeZone.getTimeZone( tzname );
+ // From luni's getTimeZone() "We never return null; on failure we return the
+ // equivalent of "GMT"." This is bad, since it'll force all invalid strings
+ // to "GMT"... and all the null-zone checks below will fail, making tzOffset
+ // irrelevant and GMT the active TZ. So tzOffset will take precedence if this
+ // results in "GMT"
+ if (TimeZone.getTimeZone("GMT").equals(zone) && tzOffset != 0) {
+ zone = null;
+ }
}
String iso = ((TelephonyManager) mPhone.getContext().
diff --git a/src/java/com/android/internal/telephony/gsm/SuppServiceNotification.java b/src/java/com/android/internal/telephony/gsm/SuppServiceNotification.java
index 8b64ade9b..7eba636e0 100644
--- a/src/java/com/android/internal/telephony/gsm/SuppServiceNotification.java
+++ b/src/java/com/android/internal/telephony/gsm/SuppServiceNotification.java
@@ -38,6 +38,9 @@ public class SuppServiceNotification {
/** List of forwarded numbers, if any */
public String[] history;
+ static public final int NOTIFICATION_TYPE_MO = 0;
+ static public final int NOTIFICATION_TYPE_MT = 1;
+
static public final int MO_CODE_UNCONDITIONAL_CF_ACTIVE = 0;
static public final int MO_CODE_SOME_CF_ACTIVE = 1;
static public final int MO_CODE_CALL_FORWARDED = 2;
@@ -64,7 +67,7 @@ public class SuppServiceNotification {
public String toString()
{
return super.toString() + " mobile"
- + (notificationType == 0 ? " originated " : " terminated ")
+ + (notificationType == NOTIFICATION_TYPE_MO ? " originated " : " terminated ")
+ " code: " + code
+ " index: " + index
+ " history: " + history
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
index 31d0ec407..652749d10 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
@@ -1755,8 +1755,6 @@ public final class ImsPhoneCallTracker extends CallTracker {
}
break;
case EVENT_DIAL_PENDINGMO:
- dialInternal(mPendingMO, mClirMode, mPendingCallVideoState,
- mPendingIntentExtras);
mPendingIntentExtras = null;
break;
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCommandInterface.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCommandInterface.java
index 11a03ec5b..037fde19e 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCommandInterface.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCommandInterface.java
@@ -610,4 +610,6 @@ class ImsPhoneCommandInterface extends BaseCommands implements CommandsInterface
@Override
public void getModemActivityInfo(Message result) {
}
+
+ public boolean needsOldRilFeature(String feature) { return false; }
}
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java
index a730693b0..5f1092f1a 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java
@@ -713,10 +713,10 @@ public class ImsPhoneConnection extends Connection {
}
boolean updateParent = mParent.update(this, imsCall, state);
+ boolean updateMediaCapabilities = updateMediaCapabilities(imsCall);
boolean updateWifiState = updateWifiState();
boolean updateAddressDisplay = updateAddressDisplay(imsCall);
boolean updateExtras = updateExtras(imsCall);
- boolean updateMediaCapabilities = updateMediaCapabilities(imsCall);
return updateParent || updateWifiState || updateAddressDisplay || updateMediaCapabilities
|| updateExtras;
diff --git a/src/java/com/android/internal/telephony/sip/SipCommandInterface.java b/src/java/com/android/internal/telephony/sip/SipCommandInterface.java
index 9631bff1a..7c73c9f6a 100644
--- a/src/java/com/android/internal/telephony/sip/SipCommandInterface.java
+++ b/src/java/com/android/internal/telephony/sip/SipCommandInterface.java
@@ -609,4 +609,5 @@ class SipCommandInterface extends BaseCommands implements CommandsInterface {
public void getModemActivityInfo(Message result) {
}
+ public boolean needsOldRilFeature(String feature) { return false; }
}
diff --git a/src/java/com/android/internal/telephony/test/SimulatedCommands.java b/src/java/com/android/internal/telephony/test/SimulatedCommands.java
index 1373e7916..028467114 100644
--- a/src/java/com/android/internal/telephony/test/SimulatedCommands.java
+++ b/src/java/com/android/internal/telephony/test/SimulatedCommands.java
@@ -1792,4 +1792,6 @@ public final class SimulatedCommands extends BaseCommands
public void getModemActivityInfo(Message result) {
unimplemented(result);
}
+
+ public boolean needsOldRilFeature(String feature) { return false; }
}
diff --git a/src/java/com/android/internal/telephony/uicc/IccRecords.java b/src/java/com/android/internal/telephony/uicc/IccRecords.java
index fcc047925..71673bc84 100644
--- a/src/java/com/android/internal/telephony/uicc/IccRecords.java
+++ b/src/java/com/android/internal/telephony/uicc/IccRecords.java
@@ -37,6 +37,8 @@ import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicBoolean;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA;
+
/**
* {@hide}
*/
@@ -62,6 +64,8 @@ public abstract class IccRecords extends Handler implements IccConstants {
protected AdnRecordCache mAdnCache;
+ private SpnOverride mSpnOverride;
+
// ***** Cached SIM State; cleared on channel close
protected boolean mRecordsRequested = false; // true if we've made requests for the sim records
@@ -130,6 +134,7 @@ public abstract class IccRecords extends Handler implements IccConstants {
+ " mCi=" + mCi
+ " mFh=" + mFh
+ " mParentApp=" + mParentApp
+ + " mSpnOverride=" + "mSpnOverride"
+ " recordsLoadedRegistrants=" + mRecordsLoadedRegistrants
+ " mImsiReadyRegistrants=" + mImsiReadyRegistrants
+ " mRecordsEventsRegistrants=" + mRecordsEventsRegistrants
@@ -178,6 +183,7 @@ public abstract class IccRecords extends Handler implements IccConstants {
mTelephonyManager = (TelephonyManager) mContext.getSystemService(
Context.TELEPHONY_SERVICE);
mCi.registerForIccRefresh(this, EVENT_REFRESH, null);
+ mSpnOverride = new SpnOverride();
}
/**
@@ -396,6 +402,16 @@ public abstract class IccRecords extends Handler implements IccConstants {
mSpn = spn;
}
+ protected void setSpnFromConfig(String carrier) {
+ if (mSpnOverride.containsCarrier(carrier)) {
+ String overrideSpn = mSpnOverride.getSpn(carrier);
+ log("set override spn carrier: " + carrier + ", spn: " + overrideSpn);
+ setServiceProviderName(overrideSpn);
+ mTelephonyManager.setSimOperatorNameForPhone(
+ mParentApp.getPhoneId(), getServiceProviderName());
+ }
+ }
+
/**
* Set voice mail number to SIM record
*
@@ -786,6 +802,7 @@ public abstract class IccRecords extends Handler implements IccConstants {
pw.println(" mCi=" + mCi);
pw.println(" mFh=" + mFh);
pw.println(" mParentApp=" + mParentApp);
+ pw.println(" mSpnOverride=" + mSpnOverride);
pw.println(" recordsLoadedRegistrants: size=" + mRecordsLoadedRegistrants.size());
for (int i = 0; i < mRecordsLoadedRegistrants.size(); i++) {
pw.println(" recordsLoadedRegistrants[" + i + "]="
diff --git a/src/java/com/android/internal/telephony/uicc/RuimRecords.java b/src/java/com/android/internal/telephony/uicc/RuimRecords.java
index 32c63faa4..d348c8125 100644
--- a/src/java/com/android/internal/telephony/uicc/RuimRecords.java
+++ b/src/java/com/android/internal/telephony/uicc/RuimRecords.java
@@ -41,6 +41,7 @@ import com.android.internal.telephony.SubscriptionController;
import com.android.internal.telephony.cdma.sms.UserData;
import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
import com.android.internal.util.BitwiseInputStream;
+import com.android.internal.telephony.uicc.UICCConfig;
/**
* {@hide}
@@ -259,6 +260,17 @@ public final class RuimRecords extends IccRecords {
return null;
}
+ if (SystemProperties.getBoolean("ro.telephony.get_imsi_from_sim", false)) {
+ String imsi = mParentApp.getUICCConfig().getImsi();
+ int mnclength = mParentApp.getUICCConfig().getMncLength();
+
+ // If we are LTE over CDMA (Verizon), then pull the correct info from SIMRecords
+ if (imsi != null) {
+ log("Overriding with Operator Numeric: " + imsi.substring(0, 3 + mnclength));
+ return imsi.substring(0, 3 + mnclength);
+ }
+ }
+
if (mMncLength != UNINITIALIZED && mMncLength != UNKNOWN) {
// Length = length of MCC + length of MNC
// length of mcc = 3 (3GPP2 C.S0005 - Section 2.3)
@@ -772,6 +784,7 @@ public final class RuimRecords extends IccRecords {
log("update icc_operator_numeric=" + operator);
mTelephonyManager.setSimOperatorNumericForPhone(
mParentApp.getPhoneId(), operator);
+ setSpnFromConfig(operator);
} else {
log("onAllRecordsLoaded empty 'gsm.sim.operator.numeric' skipping");
}
diff --git a/src/java/com/android/internal/telephony/uicc/SIMRecords.java b/src/java/com/android/internal/telephony/uicc/SIMRecords.java
index 2bb329f00..7bbee32e1 100644
--- a/src/java/com/android/internal/telephony/uicc/SIMRecords.java
+++ b/src/java/com/android/internal/telephony/uicc/SIMRecords.java
@@ -32,6 +32,7 @@ import com.android.internal.telephony.SubscriptionController;
import com.android.internal.telephony.gsm.SimTlv;
import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppState;
import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
+import com.android.internal.telephony.uicc.UICCConfig;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -51,8 +52,6 @@ public class SIMRecords extends IccRecords {
VoiceMailConstants mVmConfig;
- SpnOverride mSpnOverride;
-
// ***** Cached SIM State; cleared on channel close
private int mCallForwardingStatus;
@@ -91,7 +90,6 @@ public class SIMRecords extends IccRecords {
public String toString() {
return "SimRecords: " + super.toString()
+ " mVmConfig" + mVmConfig
- + " mSpnOverride=" + "mSpnOverride"
+ " callForwardingEnabled=" + mCallForwardingStatus
+ " spnState=" + mSpnState
+ " mCphsInfo=" + mCphsInfo
@@ -192,7 +190,6 @@ public class SIMRecords extends IccRecords {
mAdnCache = new AdnRecordCache(mFh);
mVmConfig = new VoiceMailConstants();
- mSpnOverride = new SpnOverride();
mRecordsRequested = false; // No load request is made till SIM ready
@@ -247,6 +244,8 @@ public class SIMRecords extends IccRecords {
mTelephonyManager.setSimOperatorNumericForPhone(mParentApp.getPhoneId(), "");
mTelephonyManager.setSimOperatorNameForPhone(mParentApp.getPhoneId(), "");
mTelephonyManager.setSimCountryIsoForPhone(mParentApp.getPhoneId(), "");
+ mParentApp.getUICCConfig().setImsi(mImsi);
+ mParentApp.getUICCConfig().setMncLength(mMncLength);
// recordsRequested is set to false indicating that the SIM
// read requests made so far are not valid. This is set to
@@ -684,6 +683,15 @@ public class SIMRecords extends IccRecords {
}
}
+ mParentApp.getUICCConfig().setImsi(mImsi);
+ if (mMncLength == UNKNOWN || mMncLength == UNINITIALIZED) {
+ // We need to default to something that seems common
+ mParentApp.getUICCConfig().setMncLength(3);
+ } else {
+ mParentApp.getUICCConfig().setMncLength(mMncLength);
+ }
+
+
if (mMncLength != UNKNOWN && mMncLength != UNINITIALIZED) {
log("update mccmnc=" + mImsi.substring(0, 3 + mMncLength));
// finally have both the imsi and the mncLength and can parse the imsi properly
@@ -908,7 +916,10 @@ public class SIMRecords extends IccRecords {
} else if (mMncLength != 2 && mMncLength != 3) {
mMncLength = UNINITIALIZED;
log("setting5 mMncLength=" + mMncLength);
+ } else {
+ mParentApp.getUICCConfig().setMncLength(mMncLength);
}
+
} finally {
if (((mMncLength == UNINITIALIZED) || (mMncLength == UNKNOWN) ||
(mMncLength == 2)) && ((mImsi != null) && (mImsi.length() >= 6))) {
@@ -1445,15 +1456,6 @@ public class SIMRecords extends IccRecords {
//***** Private methods
- private void setSpnFromConfig(String carrier) {
- if (mSpnOverride.containsCarrier(carrier)) {
- setServiceProviderName(mSpnOverride.getSpn(carrier));
- mTelephonyManager.setSimOperatorNameForPhone(
- mParentApp.getPhoneId(), getServiceProviderName());
- }
- }
-
-
private void setVoiceMailByCountry (String spn) {
if (mVmConfig.containsCarrier(spn)) {
mIsVoiceMailFixed = true;
@@ -1879,7 +1881,6 @@ public class SIMRecords extends IccRecords {
pw.println(" extends:");
super.dump(fd, pw, args);
pw.println(" mVmConfig=" + mVmConfig);
- pw.println(" mSpnOverride=" + mSpnOverride);
pw.println(" mCallForwardingStatus=" + mCallForwardingStatus);
pw.println(" mSpnState=" + mSpnState);
pw.println(" mCphsInfo=" + mCphsInfo);
diff --git a/src/java/com/android/internal/telephony/uicc/UICCConfig.java b/src/java/com/android/internal/telephony/uicc/UICCConfig.java
new file mode 100644
index 000000000..c814b6e48
--- /dev/null
+++ b/src/java/com/android/internal/telephony/uicc/UICCConfig.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod 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.internal.telephony.uicc;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.telephony.Rlog;
+
+/**
+ * A class that stores various UICC Settings/values.
+ * @hide
+ */
+public final class UICCConfig
+{
+ private final String PREFERENCE_NAME = "UICCConfig";
+ private final String TAG = "UICCConfig";
+ private final boolean LOG_DEBUG = false;
+
+ private String mImsi;
+ private int mMncLength;
+
+ /**
+ * A method to get the stored Imsi.
+ * @hide
+ */
+ public String getImsi() {
+ if (mImsi == null) {
+ logd("Getting IMSI: null");
+ } else {
+ logd("Getting IMSI: " + mImsi);
+ }
+ return mImsi;
+ }
+
+ /**
+ * A method to set the stored Imsi.
+ * @hide
+ */
+ public void setImsi(String lImsi) {
+ logd("Setting IMSI: " + lImsi);
+ mImsi = lImsi;
+ }
+
+ /**
+ * A method to get the stored MncLength.
+ * @hide
+ */
+ public int getMncLength() {
+ logd("Getting MncLength: " + Integer.toString(mMncLength));
+ return mMncLength;
+ }
+
+ /**
+ * A method to set the stored MncLength.
+ * @hide
+ */
+ public void setMncLength(int lMncLength) {
+ logd("Setting MncLength: " + Integer.toString(lMncLength));
+ mMncLength = lMncLength;
+ }
+
+ private void logd(String sLog) {
+ if (LOG_DEBUG) {
+ Rlog.d(TAG, sLog);
+ }
+ }
+
+ private void loge(String sLog)
+ {
+ Rlog.e(TAG, sLog);
+ }
+
+}
diff --git a/src/java/com/android/internal/telephony/uicc/UiccCard.java b/src/java/com/android/internal/telephony/uicc/UiccCard.java
index 455d189fb..4b61e5d72 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccCard.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccCard.java
@@ -83,6 +83,8 @@ public class UiccCard {
private CatService mCatService;
private RadioState mLastRadioState = RadioState.RADIO_UNAVAILABLE;
private UiccCarrierPrivilegeRules mCarrierPrivilegeRules;
+ private boolean mDefaultAppsActivated;
+ private UICCConfig mUICCConfig = null;
private RegistrantList mAbsentRegistrants = new RegistrantList();
private RegistrantList mCarrierPrivilegeRegistrants = new RegistrantList();
@@ -128,6 +130,7 @@ public class UiccCard {
mCatService = null;
mUiccApplications = null;
mCarrierPrivilegeRules = null;
+ mUICCConfig = null;
}
}
@@ -143,6 +146,8 @@ public class UiccCard {
mCi = ci;
//update applications
+ if (mUICCConfig == null)
+ mUICCConfig = new UICCConfig();
if (DBG) log(ics.mApplications.length + " applications");
for ( int i = 0; i < mUiccApplications.length; i++) {
if (mUiccApplications[i] == null) {
@@ -190,6 +195,19 @@ public class UiccCard {
mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARD_ADDED, null));
}
}
+ if (mCi.needsOldRilFeature("simactivation")) {
+ if (mCardState == CardState.CARDSTATE_PRESENT) {
+ if (!mDefaultAppsActivated) {
+ activateDefaultApps();
+ mDefaultAppsActivated = true;
+ }
+ } else {
+ // SIM removed, reset activation flag to make sure
+ // to re-run the activation at the next insertion
+ mDefaultAppsActivated = false;
+ }
+ }
+
mLastRadioState = radioState;
}
}
@@ -255,6 +273,34 @@ public class UiccCard {
return index;
}
+ private void activateDefaultApps() {
+ int gsmIndex = mGsmUmtsSubscriptionAppIndex;
+ int cdmaIndex = mCdmaSubscriptionAppIndex;
+
+ if (gsmIndex < 0 || cdmaIndex < 0) {
+ for (int i = 0; i < mUiccApplications.length; i++) {
+ if (mUiccApplications[i] == null) {
+ continue;
+ }
+
+ AppType appType = mUiccApplications[i].getType();
+ if (gsmIndex < 0
+ && (appType == AppType.APPTYPE_USIM || appType == AppType.APPTYPE_SIM)) {
+ gsmIndex = i;
+ } else if (cdmaIndex < 0 &&
+ (appType == AppType.APPTYPE_CSIM || appType == AppType.APPTYPE_RUIM)) {
+ cdmaIndex = i;
+ }
+ }
+ }
+ if (gsmIndex >= 0) {
+ mCi.setUiccSubscription(gsmIndex, true, null);
+ }
+ if (cdmaIndex >= 0) {
+ mCi.setUiccSubscription(cdmaIndex, true, null);
+ }
+ }
+
/**
* Notifies handler of any transition into State.ABSENT
*/
@@ -647,6 +693,10 @@ public class UiccCard {
return null;
}
+ public UICCConfig getUICCConfig() {
+ return mUICCConfig;
+ }
+
private void log(String msg) {
Rlog.d(LOG_TAG, msg);
}
diff --git a/src/java/com/android/internal/telephony/uicc/UiccCardApplication.java b/src/java/com/android/internal/telephony/uicc/UiccCardApplication.java
index db18ff25d..f38167e89 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccCardApplication.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccCardApplication.java
@@ -32,6 +32,7 @@ import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
import com.android.internal.telephony.uicc.IccCardApplicationStatus.PersoSubState;
import com.android.internal.telephony.uicc.IccCardStatus.PinState;
import com.android.internal.telephony.SubscriptionController;
+import com.android.internal.telephony.uicc.UICCConfig;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -885,6 +886,10 @@ public class UiccCardApplication {
return mUiccCard;
}
+ public UICCConfig getUICCConfig() {
+ return mUiccCard.getUICCConfig();
+ }
+
private void log(String msg) {
Rlog.d(LOG_TAG, msg);
}
diff --git a/src/java/com/android/internal/telephony/uicc/UiccController.java b/src/java/com/android/internal/telephony/uicc/UiccController.java
index f2aeaccc0..ead78131a 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccController.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccController.java
@@ -125,7 +125,15 @@ public class UiccController extends Handler {
for (int i = 0; i < mCis.length; i++) {
Integer index = new Integer(i);
mCis[i].registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, index);
- mCis[i].registerForAvailable(this, EVENT_ICC_STATUS_CHANGED, index);
+ // TODO remove this once modem correctly notifies the unsols
+ if (DECRYPT_STATE.equals(SystemProperties.get("vold.decrypt")) ||
+ SystemProperties.getBoolean("persist.radio.apm_sim_not_pwdn", false)) {
+ // Reading ICC status in airplane mode is only supported in QCOM
+ // RILs when this property is set to true
+ mCis[i].registerForAvailable(this, EVENT_ICC_STATUS_CHANGED, index);
+ } else {
+ mCis[i].registerForOn(this, EVENT_ICC_STATUS_CHANGED, index);
+ }
mCis[i].registerForNotAvailable(this, EVENT_RADIO_UNAVAILABLE, index);
mCis[i].registerForIccRefresh(this, EVENT_SIM_REFRESH, index);
}
diff --git a/src/java/com/android/internal/telephony/util/BlacklistUtils.java b/src/java/com/android/internal/telephony/util/BlacklistUtils.java
new file mode 100644
index 000000000..f264f8d50
--- /dev/null
+++ b/src/java/com/android/internal/telephony/util/BlacklistUtils.java
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod 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.internal.telephony.util;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.provider.Telephony.Blacklist;
+import android.telephony.PhoneNumberUtils;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.Pair;
+
+import java.util.Locale;
+
+import com.android.internal.telephony.CallerInfo;
+
+/**
+ * Blacklist Utility Class
+ * @hide
+ */
+public class BlacklistUtils {
+ private static final String TAG = "BlacklistUtils";
+ private static final boolean DEBUG = false;
+
+ // Blacklist matching type
+ public final static int MATCH_NONE = 0;
+ public final static int MATCH_PRIVATE = 1;
+ public final static int MATCH_UNKNOWN = 2;
+ public final static int MATCH_LIST = 3;
+ public final static int MATCH_REGEX = 4;
+
+ public final static int BLOCK_CALLS =
+ Settings.System.BLACKLIST_BLOCK << Settings.System.BLACKLIST_PHONE_SHIFT;
+ public final static int BLOCK_MESSAGES =
+ Settings.System.BLACKLIST_BLOCK << Settings.System.BLACKLIST_MESSAGE_SHIFT;
+
+ public static boolean addOrUpdate(Context context, String number, int flags, int valid) {
+ ContentValues cv = new ContentValues();
+
+ if ((valid & BLOCK_CALLS) != 0) {
+ cv.put(Blacklist.PHONE_MODE, (flags & BLOCK_CALLS) != 0 ? 1 : 0);
+ }
+ if ((valid & BLOCK_MESSAGES) != 0) {
+ cv.put(Blacklist.MESSAGE_MODE, (flags & BLOCK_MESSAGES) != 0 ? 1 : 0);
+ }
+
+ Uri uri = Uri.withAppendedPath(Blacklist.CONTENT_FILTER_BYNUMBER_URI, number);
+ int count = context.getContentResolver().update(uri, cv, null, null);
+
+ return count > 0;
+ }
+
+ /**
+ * Check if the number is in the blacklist
+ * @param number: Number to check
+ * @return one of: MATCH_NONE, MATCH_PRIVATE, MATCH_UNKNOWN, MATCH_LIST or MATCH_REGEX
+ */
+ public static int isListed(Context context, String number, int mode) {
+ if (!isBlacklistEnabled(context)) {
+ return MATCH_NONE;
+ }
+
+ if (DEBUG) {
+ Log.d(TAG, "Checking number " + number + " against the Blacklist for mode " + mode);
+ }
+
+ final String type;
+
+ if (mode == BLOCK_CALLS) {
+ if (DEBUG) Log.d(TAG, "Checking if an incoming call should be blocked");
+ type = Blacklist.PHONE_MODE;
+ } else if (mode == BLOCK_MESSAGES) {
+ if (DEBUG) Log.d(TAG, "Checking if an incoming message should be blocked");
+ type = Blacklist.MESSAGE_MODE;
+ } else {
+ Log.e(TAG, "Invalid mode " + mode);
+ return MATCH_NONE;
+ }
+
+ if (isBlacklistUnknownNumberEnabled(context, mode)) {
+ CallerInfo ci = CallerInfo.getCallerInfo(context, number);
+ if (ci == null || !ci.contactExists) {
+ if (DEBUG) Log.d(TAG, "Blacklist matched due to unknown number");
+ return MATCH_UNKNOWN;
+ }
+ }
+
+ // Private and unknown number matching
+ if (TextUtils.isEmpty(number)) {
+ if (isBlacklistPrivateNumberEnabled(context, mode)) {
+ if (DEBUG) Log.d(TAG, "Blacklist matched due to private number");
+ return MATCH_PRIVATE;
+ }
+ return MATCH_NONE;
+ }
+
+ Uri.Builder builder = Blacklist.CONTENT_FILTER_BYNUMBER_URI.buildUpon();
+ builder.appendPath(number);
+ if (isBlacklistRegexEnabled(context)) {
+ builder.appendQueryParameter(Blacklist.REGEX_KEY, "1");
+ }
+
+ int result = MATCH_NONE;
+ Cursor c = context.getContentResolver().query(builder.build(),
+ new String[]{Blacklist.IS_REGEX, type}, null, null, null);
+
+ if (c != null) {
+ if (DEBUG) Log.d(TAG, "Blacklist query successful, " + c.getCount() + " matches");
+ int regexColumnIndex = c.getColumnIndexOrThrow(Blacklist.IS_REGEX);
+ int modeColumnIndex = c.getColumnIndexOrThrow(type);
+ boolean whitelisted = false;
+
+ c.moveToPosition(-1);
+ while (c.moveToNext()) {
+ boolean isRegex = c.getInt(regexColumnIndex) != 0;
+ boolean blocked = c.getInt(modeColumnIndex) != 0;
+
+ if (!isRegex) {
+ whitelisted = !blocked;
+ result = MATCH_LIST;
+ if (blocked) {
+ break;
+ }
+ } else if (blocked) {
+ result = MATCH_REGEX;
+ }
+ }
+ if (whitelisted) {
+ result = MATCH_NONE;
+ }
+ c.close();
+ }
+
+ if (DEBUG) Log.d(TAG, "Blacklist check result for number " + number + " is " + result);
+ return result;
+ }
+
+ public static boolean isBlacklistEnabled(Context context) {
+ return Settings.System.getIntForUser(context.getContentResolver(),
+ Settings.System.PHONE_BLACKLIST_ENABLED, 1,
+ UserHandle.USER_CURRENT_OR_SELF) != 0;
+ }
+
+ public static boolean isBlacklistNotifyEnabled(Context context) {
+ return Settings.System.getIntForUser(context.getContentResolver(),
+ Settings.System.PHONE_BLACKLIST_NOTIFY_ENABLED, 1,
+ UserHandle.USER_CURRENT_OR_SELF) != 0;
+ }
+
+ public static boolean isBlacklistPrivateNumberEnabled(Context context, int mode) {
+ return (Settings.System.getIntForUser(context.getContentResolver(),
+ Settings.System.PHONE_BLACKLIST_PRIVATE_NUMBER_MODE, 0,
+ UserHandle.USER_CURRENT_OR_SELF) & mode) != 0;
+ }
+
+ public static boolean isBlacklistUnknownNumberEnabled(Context context, int mode) {
+ return (Settings.System.getIntForUser(context.getContentResolver(),
+ Settings.System.PHONE_BLACKLIST_UNKNOWN_NUMBER_MODE, 0,
+ UserHandle.USER_CURRENT_OR_SELF) & mode) != 0;
+ }
+
+ public static boolean isBlacklistRegexEnabled(Context context) {
+ return Settings.System.getIntForUser(context.getContentResolver(),
+ Settings.System.PHONE_BLACKLIST_REGEX_ENABLED, 0,
+ UserHandle.USER_CURRENT_OR_SELF) != 0;
+ }
+
+ public static Pair<String, Boolean> isValidBlacklistInput(Context context, String number) {
+ final Pair<String, Boolean> normalizeResult = BlacklistUtils.normalizeNumber(
+ context, number);
+ final String normalizedNumber = normalizeResult.first;
+ boolean isRegex = normalizedNumber.indexOf('%') >= 0 ||
+ normalizedNumber.indexOf('_') >= 0;
+ // For non-regex numbers, apply additional validity checking if
+ // they didn't pass e164 normalization
+ if (!isRegex && !normalizeResult.second && !BlacklistUtils.isValidPhoneNumber(number)) {
+ // number was invalid
+ return new Pair<String, Boolean>(normalizedNumber, false);
+ }
+ return new Pair<String, Boolean>(normalizedNumber, true);
+ }
+
+ /**
+ * Normalizes the passed in number and tries to format it according to E164.
+ * Returns a pair of
+ * - normalized number
+ * - boolean indicating whether the number is a E164 number or not
+ */
+ public static Pair<String, Boolean> normalizeNumber(Context context, String number) {
+ int len = number.length();
+ StringBuilder ret = new StringBuilder(len);
+
+ for (int i = 0; i < len; i++) {
+ char c = number.charAt(i);
+ // Character.digit() supports ASCII and Unicode digits (fullwidth, Arabic-Indic, etc.)
+ int digit = Character.digit(c, 10);
+ if (digit != -1) {
+ ret.append(digit);
+ } else if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
+ String actualNumber = PhoneNumberUtils.convertKeypadLettersToDigits(number);
+ return normalizeNumber(context, actualNumber);
+ } else if (i == 0 && c == '+') {
+ ret.append(c);
+ } else if (c == '*') {
+ // replace regex match-multiple character by SQL equivalent
+ ret.append('%');
+ } else if (c == '.') {
+ // replace regex-match-single character by SQL equivalent
+ ret.append('_');
+ }
+ }
+
+ String normalizedNumber = ret.toString();
+ String e164Number = toE164Number(context, normalizedNumber);
+ return Pair.create(e164Number != null ? e164Number : normalizedNumber, e164Number != null);
+ }
+
+ public static String toE164Number(Context context, String src) {
+ // Try to retrieve the current ISO Country code
+ TelephonyManager tm = (TelephonyManager)
+ context.getSystemService(Context.TELEPHONY_SERVICE);
+ String countryCode = tm.getSimCountryIso();
+ Locale numberLocale = TextUtils.isEmpty(countryCode)
+ ? context.getResources().getConfiguration().locale
+ : new Locale("", countryCode);
+
+ return PhoneNumberUtils.formatNumberToE164(src, numberLocale.getCountry());
+ }
+
+ public static boolean isValidPhoneNumber(String address) {
+ for (int i = 0, count = address.length(); i < count; i++) {
+ if (!PhoneNumberUtils.isISODigit(address.charAt(i))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static boolean isInputRegex(String input) {
+ return input.indexOf('%') >= 0 ||
+ input.indexOf('_') >= 0;
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierAppUtilsTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierAppUtilsTest.java
index 61e5b4f5c..8e016272a 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierAppUtilsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierAppUtilsTest.java
@@ -29,6 +29,7 @@ import org.mockito.MockitoAnnotations;
public class CarrierAppUtilsTest extends InstrumentationTestCase {
private static final String CARRIER_APP = "com.example.carrier";
private static final String[] CARRIER_APPS = new String[] { CARRIER_APP };
+ private static final String[] CARRIER_APPS_ENABLED = new String[0];
private static final int USER_ID = 12345;
private static final String CALLING_PACKAGE = "phone";
@@ -47,7 +48,7 @@ public class CarrierAppUtilsTest extends InstrumentationTestCase {
/** No apps configured - should do nothing. */
public void testDisableCarrierAppsUntilPrivileged_EmptyList() {
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mPackageManager,
- mTelephonyManager, USER_ID, new String[0]);
+ mTelephonyManager, USER_ID, new String[0], CARRIER_APPS_ENABLED);
Mockito.verifyNoMoreInteractions(mPackageManager, mTelephonyManager);
}
@@ -56,7 +57,7 @@ public class CarrierAppUtilsTest extends InstrumentationTestCase {
Mockito.when(mPackageManager.getApplicationInfo("com.example.missing.app",
PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS, USER_ID)).thenReturn(null);
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mPackageManager,
- mTelephonyManager, USER_ID, new String[] { "com.example.missing.app" });
+ mTelephonyManager, USER_ID, new String[] { "com.example.missing.app" }, CARRIER_APPS_ENABLED);
Mockito.verify(mPackageManager, Mockito.never()).setApplicationEnabledSetting(
Mockito.anyString(), Mockito.anyInt(), Mockito.anyInt(), Mockito.anyInt(),
Mockito.anyString());
@@ -72,7 +73,7 @@ public class CarrierAppUtilsTest extends InstrumentationTestCase {
Mockito.when(mPackageManager.getApplicationInfo(CARRIER_APP,
PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS, USER_ID)).thenReturn(appInfo);
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mPackageManager,
- mTelephonyManager, USER_ID, CARRIER_APPS);
+ mTelephonyManager, USER_ID, CARRIER_APPS, CARRIER_APPS_ENABLED);
Mockito.verify(mPackageManager, Mockito.never()).setApplicationEnabledSetting(
Mockito.anyString(), Mockito.anyInt(), Mockito.anyInt(), Mockito.anyInt(),
Mockito.anyString());
@@ -97,7 +98,7 @@ public class CarrierAppUtilsTest extends InstrumentationTestCase {
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mPackageManager,
- mTelephonyManager, USER_ID, CARRIER_APPS);
+ mTelephonyManager, USER_ID, CARRIER_APPS, CARRIER_APPS_ENABLED);
Mockito.verify(mPackageManager, Mockito.never()).setApplicationEnabledSetting(
Mockito.anyString(), Mockito.anyInt(), Mockito.anyInt(), Mockito.anyInt(),
Mockito.anyString());
@@ -116,7 +117,7 @@ public class CarrierAppUtilsTest extends InstrumentationTestCase {
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mPackageManager,
- mTelephonyManager, USER_ID, CARRIER_APPS);
+ mTelephonyManager, USER_ID, CARRIER_APPS, CARRIER_APPS_ENABLED);
Mockito.verify(mPackageManager, Mockito.never()).setApplicationEnabledSetting(
Mockito.anyString(), Mockito.anyInt(), Mockito.anyInt(), Mockito.anyInt(),
Mockito.anyString());
@@ -135,7 +136,7 @@ public class CarrierAppUtilsTest extends InstrumentationTestCase {
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mPackageManager,
- mTelephonyManager, USER_ID, CARRIER_APPS);
+ mTelephonyManager, USER_ID, CARRIER_APPS, CARRIER_APPS_ENABLED);
Mockito.verify(mPackageManager, Mockito.never()).setApplicationEnabledSetting(
Mockito.anyString(), Mockito.anyInt(), Mockito.anyInt(), Mockito.anyInt(),
Mockito.anyString());
@@ -154,7 +155,7 @@ public class CarrierAppUtilsTest extends InstrumentationTestCase {
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mPackageManager,
- mTelephonyManager, USER_ID, CARRIER_APPS);
+ mTelephonyManager, USER_ID, CARRIER_APPS, CARRIER_APPS_ENABLED);
Mockito.verify(mPackageManager, Mockito.never()).setApplicationEnabledSetting(
Mockito.anyString(), Mockito.anyInt(), Mockito.anyInt(), Mockito.anyInt(),
Mockito.anyString());
@@ -173,7 +174,7 @@ public class CarrierAppUtilsTest extends InstrumentationTestCase {
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mPackageManager,
- mTelephonyManager, USER_ID, CARRIER_APPS);
+ mTelephonyManager, USER_ID, CARRIER_APPS, CARRIER_APPS_ENABLED);
Mockito.verify(mPackageManager).setApplicationEnabledSetting(
CARRIER_APP, PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP, USER_ID, CALLING_PACKAGE);
@@ -193,7 +194,7 @@ public class CarrierAppUtilsTest extends InstrumentationTestCase {
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mPackageManager,
- mTelephonyManager, USER_ID, CARRIER_APPS);
+ mTelephonyManager, USER_ID, CARRIER_APPS, CARRIER_APPS_ENABLED);
Mockito.verify(mPackageManager).setApplicationEnabledSetting(
CARRIER_APP, PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP, USER_ID, CALLING_PACKAGE);
@@ -212,7 +213,7 @@ public class CarrierAppUtilsTest extends InstrumentationTestCase {
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mPackageManager,
- mTelephonyManager, USER_ID, CARRIER_APPS);
+ mTelephonyManager, USER_ID, CARRIER_APPS, CARRIER_APPS_ENABLED);
Mockito.verify(mPackageManager, Mockito.never()).setApplicationEnabledSetting(
Mockito.anyString(), Mockito.anyInt(), Mockito.anyInt(), Mockito.anyInt(),
Mockito.anyString());
@@ -232,7 +233,7 @@ public class CarrierAppUtilsTest extends InstrumentationTestCase {
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mPackageManager,
- mTelephonyManager, USER_ID, CARRIER_APPS);
+ mTelephonyManager, USER_ID, CARRIER_APPS, CARRIER_APPS_ENABLED);
Mockito.verify(mPackageManager, Mockito.never()).setApplicationEnabledSetting(
Mockito.anyString(), Mockito.anyInt(), Mockito.anyInt(), Mockito.anyInt(),
Mockito.anyString());
@@ -252,7 +253,7 @@ public class CarrierAppUtilsTest extends InstrumentationTestCase {
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mPackageManager,
- mTelephonyManager, USER_ID, CARRIER_APPS);
+ mTelephonyManager, USER_ID, CARRIER_APPS, CARRIER_APPS_ENABLED);
Mockito.verify(mPackageManager, Mockito.never()).setApplicationEnabledSetting(
Mockito.anyString(), Mockito.anyInt(), Mockito.anyInt(), Mockito.anyInt(),
Mockito.anyString());
@@ -272,7 +273,7 @@ public class CarrierAppUtilsTest extends InstrumentationTestCase {
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mPackageManager,
- mTelephonyManager, USER_ID, CARRIER_APPS);
+ mTelephonyManager, USER_ID, CARRIER_APPS, CARRIER_APPS_ENABLED);
Mockito.verify(mPackageManager, Mockito.never()).setApplicationEnabledSetting(
Mockito.anyString(), Mockito.anyInt(), Mockito.anyInt(), Mockito.anyInt(),
Mockito.anyString());
@@ -292,7 +293,7 @@ public class CarrierAppUtilsTest extends InstrumentationTestCase {
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mPackageManager,
- mTelephonyManager, USER_ID, CARRIER_APPS);
+ mTelephonyManager, USER_ID, CARRIER_APPS, CARRIER_APPS_ENABLED);
Mockito.verify(mPackageManager).setApplicationEnabledSetting(
CARRIER_APP, PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED, 0, USER_ID,
CALLING_PACKAGE);
@@ -313,7 +314,7 @@ public class CarrierAppUtilsTest extends InstrumentationTestCase {
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mPackageManager,
- mTelephonyManager, USER_ID, CARRIER_APPS);
+ mTelephonyManager, USER_ID, CARRIER_APPS, CARRIER_APPS_ENABLED);
Mockito.verify(mPackageManager, Mockito.never()).setApplicationEnabledSetting(
Mockito.anyString(), Mockito.anyInt(), Mockito.anyInt(), Mockito.anyInt(),
Mockito.anyString());