diff options
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()); |