am ddeba83b: Merge "Consider EF-SMS for both gsm and cdma"
* commit 'ddeba83b6c611b3c408df12ae6de8a22a4311047':
Consider EF-SMS for both gsm and cdma
diff --git a/src/java/android/provider/Telephony.java b/src/java/android/provider/Telephony.java
index 3ec38b2..82ad215 100644
--- a/src/java/android/provider/Telephony.java
+++ b/src/java/android/provider/Telephony.java
@@ -42,6 +42,64 @@
/**
* The Telephony provider contains data related to phone operation, specifically SMS and MMS
* messages and access to the APN list, including the MMSC to use.
+ *
+ * <p class="note"><strong>Note:</strong> These APIs are not available on all Android-powered
+ * devices. If your app depends on telephony features such as for managing SMS messages, include
+ * a <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code <uses-feature>}
+ * </a> element in your manifest that declares the {@code "android.hardware.telephony"} hardware
+ * feature. Alternatively, you can check for telephony availability at runtime using either
+ * {@link android.content.pm.PackageManager#hasSystemFeature
+ * hasSystemFeature(PackageManager.FEATURE_TELEPHONY)} or {@link
+ * android.telephony.TelephonyManager#getPhoneType}.</p>
+ *
+ * <h3>Creating an SMS app</h3>
+ *
+ * <p>Only the default SMS app (selected by the user in system settings) is able to write to the
+ * SMS Provider (the tables defined within the {@code Telephony} class) and only the default SMS
+ * app receives the {@link android.provider.Telephony.Sms.Intents#SMS_DELIVER_ACTION} broadcast
+ * when the user receives an SMS or the {@link
+ * android.provider.Telephony.Sms.Intents#WAP_PUSH_DELIVER_ACTION} broadcast when the user
+ * receives an MMS.</p>
+ *
+ * <p>Any app that wants to behave as the user's default SMS app must handle the following intents:
+ * <ul>
+ * <li>In a broadcast receiver, include an intent filter for {@link Sms.Intents#SMS_DELIVER_ACTION}
+ * (<code>"android.provider.Telephony.SMS_DELIVER"</code>). The broadcast receiver must also
+ * require the {@link android.Manifest.permission#BROADCAST_SMS} permission.
+ * <p>This allows your app to directly receive incoming SMS messages.</p></li>
+ * <li>In a broadcast receiver, include an intent filter for {@link
+ * Sms.Intents#WAP_PUSH_DELIVER_ACTION}} ({@code "android.provider.Telephony.WAP_PUSH_DELIVER"})
+ * with the MIME type <code>"application/vnd.wap.mms-message"</code>.
+ * The broadcast receiver must also require the {@link
+ * android.Manifest.permission#BROADCAST_WAP_PUSH} permission.
+ * <p>This allows your app to directly receive incoming MMS messages.</p></li>
+ * <li>In your activity that delivers new messages, include an intent filter for
+ * {@link android.content.Intent#ACTION_SENDTO} (<code>"android.intent.action.SENDTO"
+ * </code>) with schemas, <code>sms:</code>, <code>smsto:</code>, <code>mms:</code>, and
+ * <code>mmsto:</code>.
+ * <p>This allows your app to receive intents from other apps that want to deliver a
+ * message.</p></li>
+ * <li>In a service, include an intent filter for {@link
+ * android.telephony.TelephonyManager#ACTION_RESPOND_VIA_MESSAGE}
+ * (<code>"android.intent.action.RESPOND_VIA_MESSAGE"</code>) with schemas,
+ * <code>sms:</code>, <code>smsto:</code>, <code>mms:</code>, and <code>mmsto:</code>.
+ * This service must also require the {@link
+ * android.Manifest.permission#SEND_RESPOND_VIA_MESSAGE} permission.
+ * <p>This allows users to respond to incoming phone calls with an immediate text message
+ * using your app.</p></li>
+ * </ul>
+ *
+ * <p>Other apps that are not selected as the default SMS app can only <em>read</em> the SMS
+ * Provider, but may also be notified when a new SMS arrives by listening for the {@link
+ * Sms.Intents#SMS_RECEIVED_ACTION}
+ * broadcast, which is a non-abortable broadcast that may be delivered to multiple apps. This
+ * broadcast is intended for apps that—while not selected as the default SMS app—need to
+ * read special incoming messages such as to perform phone number verification.</p>
+ *
+ * <p>For more information about building SMS apps, read the blog post, <a
+ * href="http://android-developers.blogspot.com/2013/10/getting-your-sms-apps-ready-for-kitkat.html"
+ * >Getting Your SMS Apps Ready for KitKat</a>.</p>
+ *
*/
public final class Telephony {
private static final String TAG = "Telephony";
@@ -606,7 +664,7 @@
* the user. The intent will have the following extra values:</p>
*
* <ul>
- * <li><em>pdus</em> - An Object[] of byte[]s containing the PDUs
+ * <li><em>"pdus"</em> - An Object[] of byte[]s containing the PDUs
* that make up the message.</li>
* </ul>
*
@@ -615,6 +673,12 @@
*
* <p>If a BroadcastReceiver encounters an error while processing
* this intent it should set the result code appropriately.</p>
+ *
+ * <p class="note"><strong>Note:</strong>
+ * The broadcast receiver that filters for this intent must declare
+ * {@link android.Manifest.permission#BROADCAST_SMS} as a required permission in
+ * the <a href="{@docRoot}guide/topics/manifest/receiver-element.html">{@code
+ * <receiver>}</a> tag.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String SMS_DELIVER_ACTION =
@@ -628,7 +692,7 @@
* values:</p>
*
* <ul>
- * <li><em>pdus</em> - An Object[] of byte[]s containing the PDUs
+ * <li><em>"pdus"</em> - An Object[] of byte[]s containing the PDUs
* that make up the message.</li>
* </ul>
*
@@ -649,7 +713,7 @@
* values:</p>
*
* <ul>
- * <li><em>pdus</em> - An Object[] of byte[]s containing the PDUs
+ * <li><em>"pdus"</em> - An Object[] of byte[]s containing the PDUs
* that make up the message.</li>
* </ul>
*
@@ -670,12 +734,12 @@
* the user. The intent will have the following extra values:</p>
*
* <ul>
- * <li><em>transactionId (Integer)</em> - The WAP transaction ID</li>
- * <li><em>pduType (Integer)</em> - The WAP PDU type</li>
- * <li><em>header (byte[])</em> - The header of the message</li>
- * <li><em>data (byte[])</em> - The data payload of the message</li>
- * <li><em>contentTypeParameters (HashMap<String,String>)</em>
- * - Any parameters associated with the content type
+ * <li><em>"transactionId"</em> - (Integer) The WAP transaction ID</li>
+ * <li><em>"pduType"</em> - (Integer) The WAP PDU type</li>
+ * <li><em>"header"</em> - (byte[]) The header of the message</li>
+ * <li><em>"data"</em> - (byte[]) The data payload of the message</li>
+ * <li><em>"contentTypeParameters" </em>
+ * -(HashMap<String,String>) Any parameters associated with the content type
* (decoded from the WSP Content-Type header)</li>
* </ul>
*
@@ -688,6 +752,12 @@
* <p>If any unassigned well-known parameters are encountered, the key of the map will
* be 'unassigned/0x...', where '...' is the hex value of the unassigned parameter. If
* a parameter has No-Value the value in the map will be null.</p>
+ *
+ * <p class="note"><strong>Note:</strong>
+ * The broadcast receiver that filters for this intent must declare
+ * {@link android.Manifest.permission#BROADCAST_WAP_PUSH} as a required permission in
+ * the <a href="{@docRoot}guide/topics/manifest/receiver-element.html">{@code
+ * <receiver>}</a> tag.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String WAP_PUSH_DELIVER_ACTION =
@@ -701,12 +771,12 @@
* values:</p>
*
* <ul>
- * <li><em>transactionId (Integer)</em> - The WAP transaction ID</li>
- * <li><em>pduType (Integer)</em> - The WAP PDU type</li>
- * <li><em>header (byte[])</em> - The header of the message</li>
- * <li><em>data (byte[])</em> - The data payload of the message</li>
- * <li><em>contentTypeParameters (HashMap<String,String>)</em>
- * - Any parameters associated with the content type
+ * <li><em>"transactionId"</em> - (Integer) The WAP transaction ID</li>
+ * <li><em>"pduType"</em> - (Integer) The WAP PDU type</li>
+ * <li><em>"header"</em> - (byte[]) The header of the message</li>
+ * <li><em>"data"</em> - (byte[]) The data payload of the message</li>
+ * <li><em>"contentTypeParameters"</em>
+ * - (HashMap<String,String>) Any parameters associated with the content type
* (decoded from the WSP Content-Type header)</li>
* </ul>
*
@@ -730,7 +800,7 @@
* values:</p>
*
* <ul>
- * <li><em>message</em> - An SmsCbMessage object containing the broadcast message
+ * <li><em>"message"</em> - An SmsCbMessage object containing the broadcast message
* data. This is not an emergency alert, so ETWS and CMAS data will be null.</li>
* </ul>
*
@@ -750,7 +820,7 @@
* values:</p>
*
* <ul>
- * <li><em>message</em> - An SmsCbMessage object containing the broadcast message
+ * <li><em>"message"</em> - An SmsCbMessage object containing the broadcast message
* data, including ETWS or CMAS warning notification info if present.</li>
* </ul>
*
@@ -770,7 +840,7 @@
* have the following extra values:</p>
*
* <ul>
- * <li><em>operations</em> - An array of CdmaSmsCbProgramData objects containing
+ * <li><em>"operations"</em> - An array of CdmaSmsCbProgramData objects containing
* the service category operations (add/delete/clear) to perform.</li>
* </ul>
*
@@ -800,7 +870,7 @@
* following extra value:</p>
*
* <ul>
- * <li><em>result</em> - An int result code, e.g. {@link #RESULT_SMS_OUT_OF_MEMORY}
+ * <li><em>"result"</em> - An int result code, e.g. {@link #RESULT_SMS_OUT_OF_MEMORY}
* indicating the error returned to the network.</li>
* </ul>
*/
diff --git a/src/java/android/telephony/SmsManager.java b/src/java/android/telephony/SmsManager.java
index aa0e85b..b73cb49 100644
--- a/src/java/android/telephony/SmsManager.java
+++ b/src/java/android/telephony/SmsManager.java
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -40,7 +39,10 @@
/**
* Manages SMS operations such as sending data, text, and pdu SMS messages.
- * Get this object by calling the static method SmsManager.getDefault().
+ * Get this object by calling the static method {@link #getDefault()}.
+ *
+ * <p>For information about how to behave as the default SMS app on Android 4.4 (API level 19)
+ * and higher, see {@link android.provider.Telephony}.
*/
public final class SmsManager {
/** Singleton object constructed during class initialization. */
@@ -49,6 +51,16 @@
/**
* Send a text based SMS.
*
+ * <p class="note"><strong>Note:</strong> Using this method requires that your app has the
+ * {@link android.Manifest.permission#SEND_SMS} permission.</p>
+ *
+ * <p class="note"><strong>Note:</strong> Beginning with Android 4.4 (API level 19), if
+ * <em>and only if</em> an app is not selected as the default SMS app, the system automatically
+ * writes messages sent using this method to the SMS Provider (the default SMS app is always
+ * responsible for writing its sent messages to the SMS Provider). For information about
+ * how to behave as the default SMS app, see {@link android.provider.Telephony}.</p>
+ *
+ *
* @param destinationAddress the address to send the message to
* @param scAddress is the service center address or null to use
* the current default SMSC
@@ -116,6 +128,15 @@
* divided the message into correctly sized parts by calling
* <code>divideMessage</code>.
*
+ * <p class="note"><strong>Note:</strong> Using this method requires that your app has the
+ * {@link android.Manifest.permission#SEND_SMS} permission.</p>
+ *
+ * <p class="note"><strong>Note:</strong> Beginning with Android 4.4 (API level 19), if
+ * <em>and only if</em> an app is not selected as the default SMS app, the system automatically
+ * writes messages sent using this method to the SMS Provider (the default SMS app is always
+ * responsible for writing its sent messages to the SMS Provider). For information about
+ * how to behave as the default SMS app, see {@link android.provider.Telephony}.</p>
+ *
* @param destinationAddress the address to send the message to
* @param scAddress is the service center address or null to use
* the current default SMSC
@@ -181,6 +202,9 @@
/**
* Send a data based SMS to a specific application port.
*
+ * <p class="note"><strong>Note:</strong> Using this method requires that your app has the
+ * {@link android.Manifest.permission#SEND_SMS} permission.</p>
+ *
* @param destinationAddress the address to send the message to
* @param scAddress is the service center address or null to use
* the current default SMSC
diff --git a/src/java/android/telephony/SmsMessage.java b/src/java/android/telephony/SmsMessage.java
index d9e85d2..12d6949 100644
--- a/src/java/android/telephony/SmsMessage.java
+++ b/src/java/android/telephony/SmsMessage.java
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,6 +34,7 @@
/**
* A Short Message Service message.
+ * @see android.provider.Telephony.Sms.Intents#getMessagesFromIntent
*/
public class SmsMessage {
private static final String LOG_TAG = "SmsMessage";
diff --git a/src/java/com/android/internal/telephony/BaseCommands.java b/src/java/com/android/internal/telephony/BaseCommands.java
index c4536d0..ca3d761 100644
--- a/src/java/com/android/internal/telephony/BaseCommands.java
+++ b/src/java/com/android/internal/telephony/BaseCommands.java
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2006 The Android Open Source Project
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/java/com/android/internal/telephony/CellBroadcastHandler.java b/src/java/com/android/internal/telephony/CellBroadcastHandler.java
index 678f3e0..f7e0e3a 100644
--- a/src/java/com/android/internal/telephony/CellBroadcastHandler.java
+++ b/src/java/com/android/internal/telephony/CellBroadcastHandler.java
@@ -30,15 +30,13 @@
* completes and our result receiver is called.
*/
public class CellBroadcastHandler extends WakeLockStateMachine {
- private final Context mContext;
private CellBroadcastHandler(Context context) {
- this("CellBroadcastHandler", context);
+ this("CellBroadcastHandler", context, null);
}
- protected CellBroadcastHandler(String debugTag, Context context) {
- super(debugTag, context);
- mContext = context;
+ protected CellBroadcastHandler(String debugTag, Context context, PhoneBase phone) {
+ super(debugTag, context, phone);
}
/**
diff --git a/src/java/com/android/internal/telephony/CommandsInterface.java b/src/java/com/android/internal/telephony/CommandsInterface.java
index 252bc77..22c0fc3 100644
--- a/src/java/com/android/internal/telephony/CommandsInterface.java
+++ b/src/java/com/android/internal/telephony/CommandsInterface.java
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2006 The Android Open Source Project
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -113,11 +112,11 @@
/**
* response.obj.result is an int[2]
*
- * response.obj.result[0] is registration state
+ * response.obj.result[0] is IMS registration state
* 0 - Not registered
* 1 - Registered
- * response.obj.result[1] is of type const RIL_IMS_SMS_Format,
- * corresponds to sms format used for SMS over IMS.
+ * response.obj.result[1] is of type RILConstants.GSM_PHONE or
+ * RILConstants.CDMA_PHONE
*/
void getImsRegistrationState(Message result);
@@ -574,6 +573,9 @@
* This exception is CommandException with an error of PASSWORD_INCORRECT
* if the password is incorrect
*
+ * ar.result is an optional array of integers where the first entry
+ * is the number of attempts remaining before the ICC will be PUK locked.
+ *
* ar.exception and ar.result are null on success
*/
@@ -590,6 +592,9 @@
* This exception is CommandException with an error of PASSWORD_INCORRECT
* if the password is incorrect
*
+ * ar.result is an optional array of integers where the first entry
+ * is the number of attempts remaining before the ICC will be PUK locked.
+ *
* ar.exception and ar.result are null on success
*/
@@ -604,6 +609,9 @@
* This exception is CommandException with an error of PASSWORD_INCORRECT
* if the password is incorrect
*
+ * ar.result is an optional array of integers where the first entry
+ * is the number of attempts remaining before the ICC is permanently disabled.
+ *
* ar.exception and ar.result are null on success
*/
@@ -614,12 +622,14 @@
*
* AID (Application ID), See ETSI 102.221 8.1 and 101.220 4
*
- * returned message
* retMsg.obj = AsyncResult ar
* ar.exception carries exception on failure
* This exception is CommandException with an error of PASSWORD_INCORRECT
* if the password is incorrect
*
+ * ar.result is an optional array of integers where the first entry
+ * is the number of attempts remaining before the ICC is permanently disabled.
+ *
* ar.exception and ar.result are null on success
*/
@@ -636,6 +646,9 @@
* This exception is CommandException with an error of PASSWORD_INCORRECT
* if the password is incorrect
*
+ * ar.result is an optional array of integers where the first entry
+ * is the number of attempts remaining before the ICC will be PUK locked.
+ *
* ar.exception and ar.result are null on success
*/
@@ -654,6 +667,9 @@
* This exception is CommandException with an error of PASSWORD_INCORRECT
* if the password is incorrect
*
+ * ar.result is an optional array of integers where the first entry
+ * is the number of attempts remaining before the ICC will be PUK locked.
+ *
* ar.exception and ar.result are null on success
*/
@@ -670,6 +686,9 @@
* This exception is CommandException with an error of PASSWORD_INCORRECT
* if the password is incorrect
*
+ * ar.result is an optional array of integers where the first entry
+ * is the number of attempts remaining before the ICC is permanently disabled.
+ *
* ar.exception and ar.result are null on success
*/
@@ -688,11 +707,15 @@
* This exception is CommandException with an error of PASSWORD_INCORRECT
* if the password is incorrect
*
+ * ar.result is an optional array of integers where the first entry
+ * is the number of attempts remaining before the ICC is permanently disabled.
+ *
* ar.exception and ar.result are null on success
*/
void supplyIccPuk2ForApp(String puk2, String newPin2, String aid, Message result);
+ // TODO: Add java doc and indicate that msg.arg1 contains the number of attempts remaining.
void changeIccPin(String oldPin, String newPin, Message result);
void changeIccPinForApp(String oldPin, String newPin, String aidPtr, Message result);
void changeIccPin2(String oldPin2, String newPin2, Message result);
diff --git a/src/java/com/android/internal/telephony/IccCard.java b/src/java/com/android/internal/telephony/IccCard.java
index 1ec4f18..e5b34e2 100644
--- a/src/java/com/android/internal/telephony/IccCard.java
+++ b/src/java/com/android/internal/telephony/IccCard.java
@@ -108,6 +108,13 @@
public void supplyPuk2 (String puk2, String newPin2, Message onComplete);
/**
+ * Check whether fdn (fixed dialing number) service is available.
+ * @return true if ICC fdn service available
+ * false if ICC fdn service not available
+ */
+ public boolean getIccFdnAvailable();
+
+ /**
* Supply Network depersonalization code to the RIL
*/
public void supplyNetworkDepersonalization (String pin, Message onComplete);
@@ -214,4 +221,14 @@
* @return true if a ICC card is present
*/
public boolean hasIccCard();
+
+ /**
+ * @return true if ICC card is PIN2 blocked
+ */
+ public boolean getIccPin2Blocked();
+
+ /**
+ * @return true if ICC card is PUK2 blocked
+ */
+ public boolean getIccPuk2Blocked();
}
diff --git a/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java b/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
index a9b0409..938fd38 100644
--- a/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
+++ b/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -90,8 +89,7 @@
ar = (AsyncResult)msg.obj;
synchronized (mLock) {
if (ar.exception == null) {
- mSms = (List<SmsRawData>)
- buildValidRawData((ArrayList<byte[]>) ar.result);
+ mSms = buildValidRawData((ArrayList<byte[]>) ar.result);
//Mark SMS as read after importing it from card.
markMessagesAsRead((ArrayList<byte[]>) ar.result);
} else {
@@ -160,10 +158,6 @@
}
}
- public void dispose() {
- mDispatcher.dispose();
- }
-
protected void updatePhoneObject(PhoneBase phone) {
mPhone = phone;
mDispatcher.updatePhoneObject(phone);
diff --git a/src/java/com/android/internal/telephony/ImsSMSDispatcher.java b/src/java/com/android/internal/telephony/ImsSMSDispatcher.java
index 28919a0..07bce94 100644
--- a/src/java/com/android/internal/telephony/ImsSMSDispatcher.java
+++ b/src/java/com/android/internal/telephony/ImsSMSDispatcher.java
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2006 The Android Open Source Project
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -42,8 +41,9 @@
private SMSDispatcher mCdmaDispatcher;
private SMSDispatcher mGsmDispatcher;
- GsmInboundSmsHandler mGsmInboundSmsHandler;
- CdmaInboundSmsHandler mCdmaInboundSmsHandler;
+ private GsmInboundSmsHandler mGsmInboundSmsHandler;
+ private CdmaInboundSmsHandler mCdmaInboundSmsHandler;
+
/** true if IMS is registered and sms is supported, false otherwise.*/
private boolean mIms = false;
@@ -51,19 +51,17 @@
public ImsSMSDispatcher(PhoneBase phone, SmsStorageMonitor storageMonitor,
SmsUsageMonitor usageMonitor) {
- super(phone, usageMonitor);
+ super(phone, usageMonitor, null);
Rlog.d(TAG, "ImsSMSDispatcher created");
- // Create dispatchers, inbound SMS handlers and broadcast
- // undelivered messages in raw table.
- mCdmaDispatcher = new CdmaSMSDispatcher(phone,
- storageMonitor, usageMonitor, this);
+ // Create dispatchers, inbound SMS handlers and
+ // broadcast undelivered messages in raw table.
+ mCdmaDispatcher = new CdmaSMSDispatcher(phone, usageMonitor, this);
mGsmInboundSmsHandler = GsmInboundSmsHandler.makeInboundSmsHandler(phone.getContext(),
storageMonitor, phone);
mCdmaInboundSmsHandler = CdmaInboundSmsHandler.makeInboundSmsHandler(phone.getContext(),
storageMonitor, phone, (CdmaSMSDispatcher) mCdmaDispatcher);
- mGsmDispatcher = new GsmSMSDispatcher(phone,
- storageMonitor, usageMonitor, this, mGsmInboundSmsHandler);
+ mGsmDispatcher = new GsmSMSDispatcher(phone, usageMonitor, this, mGsmInboundSmsHandler);
Thread broadcastThread = new Thread(new SmsBroadcastUndelivered(phone.getContext(),
mGsmInboundSmsHandler, mCdmaInboundSmsHandler));
broadcastThread.start();
@@ -79,6 +77,8 @@
super.updatePhoneObject(phone);
mCdmaDispatcher.updatePhoneObject(phone);
mGsmDispatcher.updatePhoneObject(phone);
+ mGsmInboundSmsHandler.updatePhoneObject(phone);
+ mCdmaInboundSmsHandler.updatePhoneObject(phone);
}
public void dispose() {
diff --git a/src/java/com/android/internal/telephony/InboundSmsHandler.java b/src/java/com/android/internal/telephony/InboundSmsHandler.java
index 4288fcc..95a650f 100644
--- a/src/java/com/android/internal/telephony/InboundSmsHandler.java
+++ b/src/java/com/android/internal/telephony/InboundSmsHandler.java
@@ -114,6 +114,9 @@
/** Sent by {@link SmsBroadcastUndelivered} after cleaning the raw table. */
static final int EVENT_START_ACCEPTING_SMS = 6;
+ /** Update phone object */
+ static final int EVENT_UPDATE_PHONE_OBJECT = 7;
+
/** Wakelock release delay when returning to idle state. */
private static final int WAKELOCK_TIMEOUT = 3000;
@@ -145,21 +148,29 @@
final WaitingState mWaitingState = new WaitingState();
/** Helper class to check whether storage is available for incoming messages. */
- protected final SmsStorageMonitor mStorageMonitor;
+ protected SmsStorageMonitor mStorageMonitor;
private final boolean mSmsReceiveDisabled;
+ protected PhoneBase mPhone;
+
+ protected CellBroadcastHandler mCellBroadcastHandler;
+
+
/**
* Create a new SMS broadcast helper.
* @param name the class name for logging
* @param context the context of the phone app
* @param storageMonitor the SmsStorageMonitor to check for storage availability
*/
- protected InboundSmsHandler(String name, Context context, SmsStorageMonitor storageMonitor) {
+ protected InboundSmsHandler(String name, Context context, SmsStorageMonitor storageMonitor,
+ PhoneBase phone, CellBroadcastHandler cellBroadcastHandler) {
super(name);
mContext = context;
mStorageMonitor = storageMonitor;
+ mPhone = phone;
+ mCellBroadcastHandler = cellBroadcastHandler;
mResolver = context.getContentResolver();
mWapPush = new WapPushOverSms(context);
@@ -190,6 +201,13 @@
}
/**
+ * Update the phone object when it changes.
+ */
+ public void updatePhoneObject(PhoneBase phone) {
+ sendMessage(EVENT_UPDATE_PHONE_OBJECT, phone);
+ }
+
+ /**
* Dispose of the WAP push object and release the wakelock.
*/
@Override
@@ -208,13 +226,22 @@
class DefaultState extends State {
@Override
public boolean processMessage(Message msg) {
- String errorText = "processMessage: unhandled message type " + msg.what;
- if (Build.IS_DEBUGGABLE) {
- throw new RuntimeException(errorText);
- } else {
- loge(errorText);
- return HANDLED;
- }
+ switch (msg.what) {
+ case EVENT_UPDATE_PHONE_OBJECT: {
+ onUpdatePhoneObject((PhoneBase) msg.obj);
+ break;
+ }
+ default: {
+ String errorText = "processMessage: unhandled message type " + msg.what;
+ if (Build.IS_DEBUGGABLE) {
+ throw new RuntimeException(errorText);
+ } else {
+ loge(errorText);
+ }
+ break;
+ }
+ }
+ return HANDLED;
}
}
@@ -455,6 +482,19 @@
int result, Message response);
/**
+ * Called when the phone changes the default method updates mPhone
+ * mStorageMonitor and mCellBroadcastHandler.updatePhoneObject.
+ * Override if different or other behavior is desired.
+ *
+ * @param phone
+ */
+ protected void onUpdatePhoneObject(PhoneBase phone) {
+ mPhone = phone;
+ mStorageMonitor = mPhone.mSmsStorageMonitor;
+ log("onUpdatePhoneObject: phone=" + mPhone.getClass().getSimpleName());
+ }
+
+ /**
* Notify interested apps if the framework has rejected an incoming SMS,
* and send an acknowledge message to the network.
* @param success indicates that last message was successfully received.
diff --git a/src/java/com/android/internal/telephony/MccTable.java b/src/java/com/android/internal/telephony/MccTable.java
index 5613709..c57a8c4 100644
--- a/src/java/com/android/internal/telephony/MccTable.java
+++ b/src/java/com/android/internal/telephony/MccTable.java
@@ -429,7 +429,7 @@
sTable.add(new MccEntry(294,"mk",2)); //The Former Yugoslav Republic of Macedonia
sTable.add(new MccEntry(295,"li",2)); //Liechtenstein (Principality of)
sTable.add(new MccEntry(297,"me",2)); //Montenegro (Republic of)
- sTable.add(new MccEntry(302,"ca",3,"")); //Canada
+ sTable.add(new MccEntry(302,"ca",3,"en")); //Canada
sTable.add(new MccEntry(308,"pm",2)); //Saint Pierre and Miquelon (Collectivit territoriale de la Rpublique franaise)
sTable.add(new MccEntry(310,"us",3,"en")); //United States of America
sTable.add(new MccEntry(311,"us",3,"en")); //United States of America
diff --git a/src/java/com/android/internal/telephony/Phone.java b/src/java/com/android/internal/telephony/Phone.java
index 20927b9..f4e26ea 100644
--- a/src/java/com/android/internal/telephony/Phone.java
+++ b/src/java/com/android/internal/telephony/Phone.java
@@ -103,6 +103,7 @@
static final String REASON_DATA_DEPENDENCY_UNMET = "dependencyUnmet";
static final String REASON_LOST_DATA_CONNECTION = "lostDataConnection";
static final String REASON_CONNECTED = "connected";
+ static final String REASON_SINGLE_PDN_ARBITRATION = "SinglePdnArbitration";
// Used for band mode selection methods
static final int BM_UNSPECIFIED = 0; // selected by baseband automatically
diff --git a/src/java/com/android/internal/telephony/PhoneBase.java b/src/java/com/android/internal/telephony/PhoneBase.java
index 0ec5152..3e5bc4a 100644
--- a/src/java/com/android/internal/telephony/PhoneBase.java
+++ b/src/java/com/android/internal/telephony/PhoneBase.java
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2007 The Android Open Source Project
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/java/com/android/internal/telephony/PhoneFactory.java b/src/java/com/android/internal/telephony/PhoneFactory.java
index b9a6975..d7b4c8f 100644
--- a/src/java/com/android/internal/telephony/PhoneFactory.java
+++ b/src/java/com/android/internal/telephony/PhoneFactory.java
@@ -147,6 +147,9 @@
}
Rlog.i(LOG_TAG, "defaultSmsApplication: " + packageName);
+ // Set up monitor to watch for changes to SMS packages
+ SmsApplication.initSmsPackageMonitor(context);
+
sMadeDefaults = true;
}
}
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index 9b9408b..268174d 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2006 The Android Open Source Project
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -193,7 +192,7 @@
if (RIL.RILJ_LOGD) Rlog.d(LOG_TAG, serialString() + "< "
+ RIL.requestToString(mRequest)
- + " error: " + ex);
+ + " error: " + ex + " ret=" + RIL.retToString(mRequest, ret));
if (mResult != null) {
AsyncResult.forMessage(mResult, ret, ex);
@@ -1269,7 +1268,7 @@
Message result) {
RILRequest rr = RILRequest.obtain(RIL_REQUEST_IMS_SEND_SMS, result);
- rr.mParcel.writeInt(1); //RIL_IMS_SMS_Format.FORMAT_3GPP
+ rr.mParcel.writeInt(RILConstants.GSM_PHONE);
rr.mParcel.writeByte((byte)retry);
rr.mParcel.writeInt(messageRef);
@@ -1284,7 +1283,7 @@
sendImsCdmaSms(byte[] pdu, int retry, int messageRef, Message result) {
RILRequest rr = RILRequest.obtain(RIL_REQUEST_IMS_SEND_SMS, result);
- rr.mParcel.writeInt(2); //RIL_IMS_SMS_Format.FORMAT_3GPP2
+ rr.mParcel.writeInt(RILConstants.CDMA_PHONE);
rr.mParcel.writeByte((byte)retry);
rr.mParcel.writeInt(messageRef);
@@ -2505,7 +2504,7 @@
return rr;
}
- private String
+ static String
retToString(int req, Object ret) {
if (ret == null) return "";
switch (req) {
diff --git a/src/java/com/android/internal/telephony/SMSDispatcher.java b/src/java/com/android/internal/telephony/SMSDispatcher.java
index b760d37..9cd5b70 100644
--- a/src/java/com/android/internal/telephony/SMSDispatcher.java
+++ b/src/java/com/android/internal/telephony/SMSDispatcher.java
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2006 The Android Open Source Project
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -59,6 +58,7 @@
import com.android.internal.R;
import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
+import com.android.internal.telephony.ImsSMSDispatcher;
import java.util.ArrayList;
import java.util.HashMap;
@@ -128,7 +128,6 @@
protected final Context mContext;
protected final ContentResolver mResolver;
protected final CommandsInterface mCi;
- protected SmsStorageMonitor mStorageMonitor;
protected final TelephonyManager mTelephonyManager;
/** Maximum number of times to retry sending a failed SMS. */
@@ -151,6 +150,8 @@
/** Outgoing message counter. Shared by all dispatchers. */
private SmsUsageMonitor mUsageMonitor;
+ private ImsSMSDispatcher mImsSMSDispatcher;
+
/** Number of outgoing SmsTrackers waiting for user confirmation. */
private int mPendingTrackerCount;
@@ -170,8 +171,10 @@
* @param phone the Phone to use
* @param usageMonitor the SmsUsageMonitor to use
*/
- protected SMSDispatcher(PhoneBase phone, SmsUsageMonitor usageMonitor) {
+ protected SMSDispatcher(PhoneBase phone, SmsUsageMonitor usageMonitor,
+ ImsSMSDispatcher imsSMSDispatcher) {
mPhone = phone;
+ mImsSMSDispatcher = imsSMSDispatcher;
mContext = phone.getContext();
mResolver = mContext.getContentResolver();
mCi = phone.mCi;
@@ -211,7 +214,6 @@
protected void updatePhoneObject(PhoneBase phone) {
mPhone = phone;
- mStorageMonitor = phone.mSmsStorageMonitor;
mUsageMonitor = phone.mSmsUsageMonitor;
Rlog.d(TAG, "Active phone changed to " + mPhone.getPhoneName() );
}
@@ -341,11 +343,10 @@
if (ar.exception == null) {
if (DBG) Rlog.d(TAG, "SMS send complete. Broadcasting intent: " + sentIntent);
- String defaultSmsPackage = Sms.getDefaultSmsPackage(mContext);
- if (defaultSmsPackage == null ||
- !defaultSmsPackage.equals(tracker.mAppInfo.applicationInfo.packageName)) {
- // Someone other than the default SMS app sent this message. Persist it into the
- // SMS database as a sent message so the user can see it in their default app.
+ if (SmsApplication.shouldWriteMessageForPackage(
+ tracker.mAppInfo.applicationInfo.packageName, mContext)) {
+ // Persist it into the SMS database as a sent message
+ // so the user can see it in their default app.
tracker.writeSentMessage(mContext);
}
@@ -945,7 +946,14 @@
*
* @param tracker holds the SMS message to send
*/
- public abstract void sendRetrySms(SmsTracker tracker);
+ public void sendRetrySms(SmsTracker tracker) {
+ // re-routing to ImsSMSDispatcher
+ if (mImsSMSDispatcher != null) {
+ mImsSMSDispatcher.sendRetrySms(tracker);
+ } else {
+ Rlog.e(TAG, mImsSMSDispatcher + " is null. Retry failed");
+ }
+ }
/**
* Send the multi-part SMS based on multipart Sms tracker
@@ -1060,7 +1068,7 @@
}
}
- protected SmsTracker SmsTrackerFactory(HashMap<String, Object> data, PendingIntent sentIntent,
+ protected SmsTracker getSmsTracker(HashMap<String, Object> data, PendingIntent sentIntent,
PendingIntent deliveryIntent, String format) {
// Get calling app package name via UID from Binder call
PackageManager pm = mContext.getPackageManager();
@@ -1082,7 +1090,7 @@
return new SmsTracker(data, sentIntent, deliveryIntent, appInfo, destAddr, format);
}
- protected HashMap SmsTrackerMapFactory(String destAddr, String scAddr,
+ protected HashMap<String, Object> getSmsTrackerMap(String destAddr, String scAddr,
String text, SmsMessageBase.SubmitPduBase pdu) {
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("destAddr", destAddr);
@@ -1093,12 +1101,12 @@
return map;
}
- protected HashMap SmsTrackerMapFactory(String destAddr, String scAddr,
+ protected HashMap<String, Object> getSmsTrackerMap(String destAddr, String scAddr,
int destPort, byte[] data, SmsMessageBase.SubmitPduBase pdu) {
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("destAddr", destAddr);
map.put("scAddr", scAddr);
- map.put("destPort", Integer.valueOf(destPort));
+ map.put("destPort", destPort);
map.put("data", data);
map.put("smsc", pdu.encodedScAddress);
map.put("pdu", pdu.encodedMessage);
@@ -1190,7 +1198,21 @@
}
}
- public abstract boolean isIms();
+ public boolean isIms() {
+ if (mImsSMSDispatcher != null) {
+ return mImsSMSDispatcher.isIms();
+ } else {
+ Rlog.e(TAG, mImsSMSDispatcher + " is null");
+ return false;
+ }
+ }
- public abstract String getImsSmsFormat();
+ public String getImsSmsFormat() {
+ if (mImsSMSDispatcher != null) {
+ return mImsSMSDispatcher.getImsSmsFormat();
+ } else {
+ Rlog.e(TAG, mImsSMSDispatcher + " is null");
+ return null;
+ }
+ }
}
diff --git a/src/java/com/android/internal/telephony/SmsApplication.java b/src/java/com/android/internal/telephony/SmsApplication.java
index dc0bf29..80ae2b8 100644
--- a/src/java/com/android/internal/telephony/SmsApplication.java
+++ b/src/java/com/android/internal/telephony/SmsApplication.java
@@ -21,6 +21,7 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -33,6 +34,7 @@
import android.provider.Telephony.Sms.Intents;
import android.telephony.Rlog;
import android.telephony.TelephonyManager;
+import com.android.internal.content.PackageMonitor;
import java.util.Collection;
import java.util.HashMap;
@@ -46,6 +48,14 @@
public final class SmsApplication {
static final String LOG_TAG = "SmsApplication";
private static final String PHONE_PACKAGE_NAME = "com.android.phone";
+ private static final String BLUETOOTH_PACKAGE_NAME = "com.android.bluetooth";
+
+ private static final String SCHEME_SMS = "sms";
+ private static final String SCHEME_SMSTO = "smsto";
+ private static final String SCHEME_MMS = "mms";
+ private static final String SCHEME_MMSTO = "mmsto";
+
+ private static SmsPackageMonitor sSmsPackageMonitor = null;
public static class SmsApplicationData {
/**
@@ -167,7 +177,7 @@
// Update any existing entries with respond via message intent class.
intent = new Intent(TelephonyManager.ACTION_RESPOND_VIA_MESSAGE,
- Uri.fromParts("smsto", "", null));
+ Uri.fromParts(SCHEME_SMSTO, "", null));
List<ResolveInfo> respondServices = packageManager.queryIntentServices(intent, 0);
for (ResolveInfo resolveInfo : respondServices) {
final ServiceInfo serviceInfo = resolveInfo.serviceInfo;
@@ -186,7 +196,7 @@
// Update any existing entries with supports send to.
intent = new Intent(Intent.ACTION_SENDTO,
- Uri.fromParts("smsto", "", null));
+ Uri.fromParts(SCHEME_SMSTO, "", null));
List<ResolveInfo> sendToActivities = packageManager.queryIntentActivities(intent, 0);
for (ResolveInfo resolveInfo : sendToActivities) {
final ActivityInfo activityInfo = resolveInfo.activityInfo;
@@ -308,10 +318,17 @@
}
}
- // We can only verify the phone app's permissions from a privileged caller
+ // We can only verify the phone and BT app's permissions from a privileged caller
if (updateIfNeeded) {
- // Verify that the phone app has permissions
+ // Ensure this component is still configured as the preferred activity. Usually the
+ // current SMS app will already be the preferred activity - but checking whether or
+ // not this is true is just as expensive as reconfiguring the preferred activity so
+ // we just reconfigure every time.
PackageManager packageManager = context.getPackageManager();
+ configurePreferredActivity(packageManager, new ComponentName(
+ applicationData.mPackageName, applicationData.mSendToClass));
+
+ // Verify that the phone and BT app has permissions
try {
PackageInfo info = packageManager.getPackageInfo(PHONE_PACKAGE_NAME, 0);
int mode = appOps.checkOp(AppOpsManager.OP_WRITE_SMS, info.applicationInfo.uid,
@@ -326,6 +343,20 @@
Rlog.e(LOG_TAG, "Phone package not found: " + PHONE_PACKAGE_NAME);
applicationData = null;
}
+
+ try {
+ PackageInfo info = packageManager.getPackageInfo(BLUETOOTH_PACKAGE_NAME, 0);
+ int mode = appOps.checkOp(AppOpsManager.OP_WRITE_SMS, info.applicationInfo.uid,
+ BLUETOOTH_PACKAGE_NAME);
+ if (mode != AppOpsManager.MODE_ALLOWED) {
+ Rlog.e(LOG_TAG, BLUETOOTH_PACKAGE_NAME + " lost OP_WRITE_SMS: (fixing)");
+ appOps.setMode(AppOpsManager.OP_WRITE_SMS, info.applicationInfo.uid,
+ BLUETOOTH_PACKAGE_NAME, AppOpsManager.MODE_ALLOWED);
+ }
+ } catch (NameNotFoundException e) {
+ // No BT app on this device
+ Rlog.e(LOG_TAG, "Bluetooth package not found: " + BLUETOOTH_PACKAGE_NAME);
+ }
}
}
return applicationData;
@@ -373,6 +404,10 @@
Settings.Secure.putString(context.getContentResolver(),
Settings.Secure.SMS_DEFAULT_APPLICATION, applicationData.mPackageName);
+ // Configure this as the preferred activity for SENDTO sms/mms intents
+ configurePreferredActivity(packageManager, new ComponentName(
+ applicationData.mPackageName, applicationData.mSendToClass));
+
// Allow OP_WRITE_SMS for the newly configured default SMS app.
appOps.setMode(AppOpsManager.OP_WRITE_SMS, applicationData.mUid,
applicationData.mPackageName, AppOpsManager.MODE_ALLOWED);
@@ -386,10 +421,99 @@
// No phone app on this device (unexpected, even for non-phone devices)
Rlog.e(LOG_TAG, "Phone package not found: " + PHONE_PACKAGE_NAME);
}
+
+ // BT needs to always have this permission to write to the sms database
+ try {
+ PackageInfo info = packageManager.getPackageInfo(BLUETOOTH_PACKAGE_NAME, 0);
+ appOps.setMode(AppOpsManager.OP_WRITE_SMS, info.applicationInfo.uid,
+ BLUETOOTH_PACKAGE_NAME, AppOpsManager.MODE_ALLOWED);
+ } catch (NameNotFoundException e) {
+ // No BT app on this device
+ Rlog.e(LOG_TAG, "Bluetooth package not found: " + BLUETOOTH_PACKAGE_NAME);
+ }
}
}
/**
+ * Tracks package changes and ensures that the default SMS app is always configured to be the
+ * preferred activity for SENDTO sms/mms intents.
+ */
+ private static final class SmsPackageMonitor extends PackageMonitor {
+ final Context mContext;
+
+ public SmsPackageMonitor(Context context) {
+ super();
+ mContext = context;
+ }
+
+ @Override
+ public void onPackageDisappeared(String packageName, int reason) {
+ onPackageChanged(packageName);
+ }
+
+ @Override
+ public void onPackageAppeared(String packageName, int reason) {
+ onPackageChanged(packageName);
+ }
+
+ @Override
+ public void onPackageModified(String packageName) {
+ onPackageChanged(packageName);
+ }
+
+ private void onPackageChanged(String packageName) {
+ PackageManager packageManager = mContext.getPackageManager();
+ // Ensure this component is still configured as the preferred activity
+ ComponentName componentName = getDefaultSendToApplication(mContext, true);
+ if (componentName != null) {
+ configurePreferredActivity(packageManager, componentName);
+ }
+ }
+ }
+
+ public static void initSmsPackageMonitor(Context context) {
+ sSmsPackageMonitor = new SmsPackageMonitor(context);
+ sSmsPackageMonitor.register(context, context.getMainLooper(), false);
+ }
+
+ private static void configurePreferredActivity(PackageManager packageManager,
+ ComponentName componentName) {
+ // Add the four activity preferences we want to direct to this app.
+ replacePreferredActivity(packageManager, componentName, SCHEME_SMS);
+ replacePreferredActivity(packageManager, componentName, SCHEME_SMSTO);
+ replacePreferredActivity(packageManager, componentName, SCHEME_MMS);
+ replacePreferredActivity(packageManager, componentName, SCHEME_MMSTO);
+ }
+
+ /**
+ * Updates the ACTION_SENDTO activity to the specified component for the specified scheme.
+ */
+ private static void replacePreferredActivity(PackageManager packageManager,
+ ComponentName componentName, String scheme) {
+ // Build the set of existing activities that handle this scheme
+ Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts(scheme, "", null));
+ List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivities(
+ intent, PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_RESOLVED_FILTER);
+
+ // Build the set of ComponentNames for these activities
+ final int n = resolveInfoList.size();
+ ComponentName[] set = new ComponentName[n];
+ for (int i = 0; i < n; i++) {
+ ResolveInfo info = resolveInfoList.get(i);
+ set[i] = new ComponentName(info.activityInfo.packageName, info.activityInfo.name);
+ }
+
+ // Update the preferred SENDTO activity for the specified scheme
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(Intent.ACTION_SENDTO);
+ intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
+ intentFilter.addDataScheme(scheme);
+ packageManager.replacePreferredActivity(intentFilter,
+ IntentFilter.MATCH_CATEGORY_SCHEME + IntentFilter.MATCH_ADJUSTMENT_NORMAL,
+ set, componentName);
+ }
+
+ /**
* Returns SmsApplicationData for this package if this package is capable of being set as the
* default SMS application.
*/
@@ -463,4 +587,25 @@
}
return component;
}
+
+ /**
+ * Returns whether need to write the SMS message to SMS database for this package.
+ */
+ public static boolean shouldWriteMessageForPackage(String packageName, Context context) {
+ if (packageName == null) return true;
+
+ String defaultSmsPackage = null;
+ ComponentName component = getDefaultSmsApplication(context, false);
+ if (component != null) {
+ defaultSmsPackage = component.getPackageName();
+ }
+
+ if ((defaultSmsPackage == null || !defaultSmsPackage.equals(packageName)) &&
+ !packageName.equals(BLUETOOTH_PACKAGE_NAME)) {
+ // To write the message for someone other than the default SMS and BT app
+ return true;
+ }
+
+ return false;
+ }
}
diff --git a/src/java/com/android/internal/telephony/WakeLockStateMachine.java b/src/java/com/android/internal/telephony/WakeLockStateMachine.java
index ef1b68e..404b0cc 100644
--- a/src/java/com/android/internal/telephony/WakeLockStateMachine.java
+++ b/src/java/com/android/internal/telephony/WakeLockStateMachine.java
@@ -48,6 +48,12 @@
/** Release wakelock after a short timeout when returning to idle state. */
static final int EVENT_RELEASE_WAKE_LOCK = 3;
+ static final int EVENT_UPDATE_PHONE_OBJECT = 4;
+
+ protected PhoneBase mPhone;
+
+ protected Context mContext;
+
/** Wakelock release delay when returning to idle state. */
private static final int WAKE_LOCK_TIMEOUT = 3000;
@@ -55,9 +61,12 @@
private final IdleState mIdleState = new IdleState();
private final WaitingState mWaitingState = new WaitingState();
- protected WakeLockStateMachine(String debugTag, Context context) {
+ protected WakeLockStateMachine(String debugTag, Context context, PhoneBase phone) {
super(debugTag);
+ mContext = context;
+ mPhone = phone;
+
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, debugTag);
mWakeLock.acquire(); // wake lock released after we enter idle state
@@ -68,6 +77,10 @@
setInitialState(mIdleState);
}
+ public void updatePhoneObject(PhoneBase phone) {
+ sendMessage(EVENT_UPDATE_PHONE_OBJECT, phone);
+ }
+
/**
* Tell the state machine to quit after processing all messages.
*/
@@ -98,13 +111,23 @@
class DefaultState extends State {
@Override
public boolean processMessage(Message msg) {
- String errorText = "processMessage: unhandled message type " + msg.what;
- if (Build.IS_DEBUGGABLE) {
- throw new RuntimeException(errorText);
- } else {
- loge(errorText);
- return HANDLED;
- }
+ switch (msg.what) {
+ case EVENT_UPDATE_PHONE_OBJECT: {
+ mPhone = (PhoneBase) msg.obj;
+ log("updatePhoneObject: phone=" + mPhone.getClass().getSimpleName());
+ break;
+ }
+ default: {
+ String errorText = "processMessage: unhandled message type " + msg.what;
+ if (Build.IS_DEBUGGABLE) {
+ throw new RuntimeException(errorText);
+ } else {
+ loge(errorText);
+ }
+ break;
+ }
+ }
+ return HANDLED;
}
}
diff --git a/src/java/com/android/internal/telephony/cdma/CDMALTEPhone.java b/src/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
index 1f9368a..3b6856d 100644
--- a/src/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
+++ b/src/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
@@ -1,6 +1,5 @@
/*
- * Copyrigh (C) 2011 The Android Open Source Project
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -196,6 +195,27 @@
}
+
+ /**
+ * Sets the "current" field in the telephony provider according to the
+ * build-time operator numeric property
+ *
+ * @return true for success; false otherwise.
+ */
+ @Override
+ boolean updateCurrentCarrierInProvider(String operatorNumeric) {
+ boolean retVal;
+ if (mUiccController.getUiccCardApplication(UiccController.APP_FAM_3GPP) == null) {
+ if (DBG) log("updateCurrentCarrierInProvider APP_FAM_3GPP == null");
+ retVal = super.updateCurrentCarrierInProvider(operatorNumeric);
+ } else {
+ if (DBG) log("updateCurrentCarrierInProvider not updated");
+ retVal = true;
+ }
+ if (DBG) log("updateCurrentCarrierInProvider X retVal=" + retVal);
+ return retVal;
+ }
+
@Override
public boolean updateCurrentCarrierInProvider() {
if (mSimRecords != null) {
diff --git a/src/java/com/android/internal/telephony/cdma/CDMAPhone.java b/src/java/com/android/internal/telephony/cdma/CDMAPhone.java
index 38524df..ccffeae 100644
--- a/src/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/src/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2006 The Android Open Source Project
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -196,22 +195,24 @@
mCarrierOtaSpNumSchema = SystemProperties.get(
TelephonyProperties.PROPERTY_OTASP_NUM_SCHEMA,"");
- // Sets operator alpha property by retrieving from build-time system property
+ // Sets operator properties by retrieving from build-time system property
String operatorAlpha = SystemProperties.get("ro.cdma.home.operator.alpha");
- setSystemProperty(PROPERTY_ICC_OPERATOR_ALPHA, operatorAlpha);
-
- // Sets operator numeric property by retrieving from build-time system property
String operatorNumeric = SystemProperties.get(PROPERTY_CDMA_HOME_OPERATOR_NUMERIC);
- if (!TextUtils.isEmpty(operatorNumeric) &&
- (mUiccController.getUiccCardApplication(UiccController.APP_FAM_3GPP) == null)) {
- log("CDMAPhone: init set 'gsm.sim.operator.numeric' to operator='" +
- operatorNumeric + "'");
- setSystemProperty(PROPERTY_ICC_OPERATOR_NUMERIC, operatorNumeric);
+ log("init: operatorAlpha='" + operatorAlpha
+ + "' operatorNumeric='" + operatorNumeric + "'");
+ if (mUiccController.getUiccCardApplication(UiccController.APP_FAM_3GPP) == null) {
+ log("init: APP_FAM_3GPP == NULL");
+ if (!TextUtils.isEmpty(operatorAlpha)) {
+ log("init: set 'gsm.sim.operator.alpha' to operator='" + operatorAlpha + "'");
+ setSystemProperty(PROPERTY_ICC_OPERATOR_ALPHA, operatorAlpha);
+ }
+ if (!TextUtils.isEmpty(operatorNumeric)) {
+ log("init: set 'gsm.sim.operator.numeric' to operator='" + operatorNumeric + "'");
+ setSystemProperty(PROPERTY_ICC_OPERATOR_NUMERIC, operatorNumeric);
+ }
+ setIsoCountryProperty(operatorNumeric);
}
- // Sets iso country property by retrieving from build-time system property
- setIsoCountryProperty(operatorNumeric);
-
// Sets current entry in the telephony carrier table
updateCurrentCarrierInProvider(operatorNumeric);
@@ -575,12 +576,12 @@
@Override
public boolean handlePinMmi(String dialString) {
- CdmaMmiCode mmi = CdmaMmiCode.newFromDialString(dialString, this);
+ CdmaMmiCode mmi = CdmaMmiCode.newFromDialString(dialString, this, mUiccApplication.get());
if (mmi == null) {
Rlog.e(LOG_TAG, "Mmi is NULL!");
return false;
- } else if (mmi.isPukCommand()) {
+ } else if (mmi.isPinPukCommand()) {
mPendingMmis.add(mmi);
mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
mmi.processCode();
@@ -1544,6 +1545,7 @@
*/
private void setIsoCountryProperty(String operatorNumeric) {
if (TextUtils.isEmpty(operatorNumeric)) {
+ log("setIsoCountryProperty: clear 'gsm.sim.operator.iso-country'");
setSystemProperty(PROPERTY_ICC_OPERATOR_ISO_COUNTRY, "");
} else {
String iso = "";
@@ -1551,11 +1553,12 @@
iso = MccTable.countryCodeForMcc(Integer.parseInt(
operatorNumeric.substring(0,3)));
} catch (NumberFormatException ex) {
- Rlog.w(LOG_TAG, "countryCodeForMcc error" + ex);
+ loge("setIsoCountryProperty: countryCodeForMcc error", ex);
} catch (StringIndexOutOfBoundsException ex) {
- Rlog.w(LOG_TAG, "countryCodeForMcc error" + ex);
+ loge("setIsoCountryProperty: countryCodeForMcc error", ex);
}
+ log("setIsoCountryProperty: set 'gsm.sim.operator.iso-country' to iso=" + iso);
setSystemProperty(PROPERTY_ICC_OPERATOR_ISO_COUNTRY, iso);
}
}
@@ -1567,6 +1570,7 @@
* @return true for success; false otherwise.
*/
boolean updateCurrentCarrierInProvider(String operatorNumeric) {
+ log("CDMAPhone: updateCurrentCarrierInProvider called");
if (!TextUtils.isEmpty(operatorNumeric)) {
try {
Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current");
@@ -1632,6 +1636,11 @@
Rlog.d(LOG_TAG, s);
}
+ protected void loge(String s, Exception e) {
+ if (DBG)
+ Rlog.e(LOG_TAG, s, e);
+ }
+
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("CDMAPhone extends:");
diff --git a/src/java/com/android/internal/telephony/cdma/CdmaInboundSmsHandler.java b/src/java/com/android/internal/telephony/cdma/CdmaInboundSmsHandler.java
index 99e790f..9352639 100644
--- a/src/java/com/android/internal/telephony/cdma/CdmaInboundSmsHandler.java
+++ b/src/java/com/android/internal/telephony/cdma/CdmaInboundSmsHandler.java
@@ -45,9 +45,7 @@
*/
public class CdmaInboundSmsHandler extends InboundSmsHandler {
- private final PhoneBase mPhone;
private final CdmaSMSDispatcher mSmsDispatcher;
- private final CellBroadcastHandler mCellBroadcastHandler;
private final CdmaServiceCategoryProgramHandler mServiceCategoryProgramHandler;
private byte[] mLastDispatchedSmsFingerprint;
@@ -61,12 +59,11 @@
*/
private CdmaInboundSmsHandler(Context context, SmsStorageMonitor storageMonitor,
PhoneBase phone, CdmaSMSDispatcher smsDispatcher) {
- super("CdmaInboundSmsHandler", context, storageMonitor);
+ super("CdmaInboundSmsHandler", context, storageMonitor, phone,
+ CellBroadcastHandler.makeCellBroadcastHandler(context));
mSmsDispatcher = smsDispatcher;
- mCellBroadcastHandler = CellBroadcastHandler.makeCellBroadcastHandler(context);
mServiceCategoryProgramHandler = CdmaServiceCategoryProgramHandler.makeScpHandler(context,
phone.mCi);
- mPhone = phone;
phone.mCi.setOnNewCdmaSms(getHandler(), EVENT_NEW_SMS, null);
}
@@ -214,6 +211,19 @@
}
/**
+ * Called when the phone changes the default method updates mPhone
+ * mStorageMonitor and mCellBroadcastHandler.updatePhoneObject.
+ * Override if different or other behavior is desired.
+ *
+ * @param phone
+ */
+ @Override
+ protected void onUpdatePhoneObject(PhoneBase phone) {
+ super.onUpdatePhoneObject(phone);
+ mCellBroadcastHandler.updatePhoneObject(phone);
+ }
+
+ /**
* Convert Android result code to CDMA SMS failure cause.
* @param rc the Android SMS intent result value
* @return 0 for success, or a CDMA SMS failure cause value
diff --git a/src/java/com/android/internal/telephony/cdma/CdmaMmiCode.java b/src/java/com/android/internal/telephony/cdma/CdmaMmiCode.java
index 4c58709..3cb8bc7 100644
--- a/src/java/com/android/internal/telephony/cdma/CdmaMmiCode.java
+++ b/src/java/com/android/internal/telephony/cdma/CdmaMmiCode.java
@@ -19,6 +19,8 @@
import android.content.Context;
import com.android.internal.telephony.CommandException;
+import com.android.internal.telephony.uicc.UiccCardApplication;
+import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppState;
import com.android.internal.telephony.MmiCode;
import android.os.AsyncResult;
@@ -43,8 +45,11 @@
// From TS 22.030 6.5.2
static final String ACTION_REGISTER = "**";
- // Supp Service codes from TS 22.030 Annex B
+ // Supplementary Service codes for PIN/PIN2/PUK/PUK2 from TS 22.030 Annex B
+ static final String SC_PIN = "04";
+ static final String SC_PIN2 = "042";
static final String SC_PUK = "05";
+ static final String SC_PUK2 = "052";
// Event Constant
@@ -54,6 +59,7 @@
CDMAPhone mPhone;
Context mContext;
+ UiccCardApplication mUiccApplication;
String mAction; // ACTION_REGISTER
String mSc; // Service Code
@@ -98,7 +104,7 @@
*/
public static CdmaMmiCode
- newFromDialString(String dialString, CDMAPhone phone) {
+ newFromDialString(String dialString, CDMAPhone phone, UiccCardApplication app) {
Matcher m;
CdmaMmiCode ret = null;
@@ -106,7 +112,7 @@
// Is this formatted like a standard supplementary service code?
if (m.matches()) {
- ret = new CdmaMmiCode(phone);
+ ret = new CdmaMmiCode(phone,app);
ret.mPoundString = makeEmptyNull(m.group(MATCH_GROUP_POUND_STRING));
ret.mAction = makeEmptyNull(m.group(MATCH_GROUP_ACTION));
ret.mSc = makeEmptyNull(m.group(MATCH_GROUP_SERVICE_CODE));
@@ -135,10 +141,11 @@
// Constructor
- CdmaMmiCode (CDMAPhone phone) {
+ CdmaMmiCode (CDMAPhone phone, UiccCardApplication app) {
super(phone.getHandler().getLooper());
mPhone = phone;
mContext = phone.getContext();
+ mUiccApplication = app;
}
// MmiCode implementation
@@ -178,9 +185,10 @@
/**
* @return true if the Service Code is PIN/PIN2/PUK/PUK2-related
*/
- boolean isPukCommand() {
- return mSc != null && mSc.equals(SC_PUK);
- }
+ boolean isPinPukCommand() {
+ return mSc != null && (mSc.equals(SC_PIN) || mSc.equals(SC_PIN2)
+ || mSc.equals(SC_PUK) || mSc.equals(SC_PUK2));
+ }
boolean isRegister() {
return mAction != null && mAction.equals(ACTION_REGISTER);
@@ -194,31 +202,56 @@
/** Process a MMI PUK code */
void
- processCode () {
+ processCode() {
try {
- if (isPukCommand()) {
- // sia = old PUK
+ if (isPinPukCommand()) {
+ // TODO: This is the same as the code in GsmMmiCode.java,
+ // MmiCode should be an abstract or base class and this and
+ // other common variables and code should be promoted.
+
+ // sia = old PIN or PUK
// sib = new PIN
// sic = new PIN
String oldPinOrPuk = mSia;
- String newPin = mSib;
- int pinLen = newPin.length();
+ String newPinOrPuk = mSib;
+ int pinLen = newPinOrPuk.length();
if (isRegister()) {
- if (!newPin.equals(mSic)) {
+ if (!newPinOrPuk.equals(mSic)) {
// password mismatch; return error
handlePasswordError(com.android.internal.R.string.mismatchPin);
} else if (pinLen < 4 || pinLen > 8 ) {
// invalid length
handlePasswordError(com.android.internal.R.string.invalidPin);
+ } else if (mSc.equals(SC_PIN)
+ && mUiccApplication != null
+ && mUiccApplication.getState() == AppState.APPSTATE_PUK) {
+ // Sim is puk-locked
+ handlePasswordError(com.android.internal.R.string.needPuk);
+ } else if (mUiccApplication != null) {
+ Rlog.d(LOG_TAG, "process mmi service code using UiccApp sc=" + mSc);
+
+ // We have an app and the pre-checks are OK
+ if (mSc.equals(SC_PIN)) {
+ mUiccApplication.changeIccLockPassword(oldPinOrPuk, newPinOrPuk,
+ obtainMessage(EVENT_SET_COMPLETE, this));
+ } else if (mSc.equals(SC_PIN2)) {
+ mUiccApplication.changeIccFdnPassword(oldPinOrPuk, newPinOrPuk,
+ obtainMessage(EVENT_SET_COMPLETE, this));
+ } else if (mSc.equals(SC_PUK)) {
+ mUiccApplication.supplyPuk(oldPinOrPuk, newPinOrPuk,
+ obtainMessage(EVENT_SET_COMPLETE, this));
+ } else if (mSc.equals(SC_PUK2)) {
+ mUiccApplication.supplyPuk2(oldPinOrPuk, newPinOrPuk,
+ obtainMessage(EVENT_SET_COMPLETE, this));
+ } else {
+ throw new RuntimeException("Unsupported service code=" + mSc);
+ }
} else {
- mPhone.mCi.supplyIccPuk(oldPinOrPuk, newPin,
- obtainMessage(EVENT_SET_COMPLETE, this));
+ throw new RuntimeException("No application mUiccApplicaiton is null");
}
} else {
- throw new RuntimeException ("Invalid or Unsupported MMI Code");
+ throw new RuntimeException ("Ivalid register/action=" + mAction);
}
- } else {
- throw new RuntimeException ("Invalid or Unsupported MMI Code");
}
} catch (RuntimeException exc) {
mState = State.FAILED;
@@ -243,7 +276,7 @@
if (msg.what == EVENT_SET_COMPLETE) {
ar = (AsyncResult) (msg.obj);
- onSetComplete(ar);
+ onSetComplete(msg, ar);
} else {
Rlog.e(LOG_TAG, "Unexpected reply");
}
@@ -252,7 +285,7 @@
private CharSequence getScString() {
if (mSc != null) {
- if (isPukCommand()) {
+ if (isPinPukCommand()) {
return mContext.getText(com.android.internal.R.string.PinMmi);
}
}
@@ -261,7 +294,7 @@
}
private void
- onSetComplete(AsyncResult ar){
+ onSetComplete(Message msg, AsyncResult ar){
StringBuilder sb = new StringBuilder(getScString());
sb.append("\n");
@@ -270,13 +303,42 @@
if (ar.exception instanceof CommandException) {
CommandException.Error err = ((CommandException)(ar.exception)).getCommandError();
if (err == CommandException.Error.PASSWORD_INCORRECT) {
- if (isPukCommand()) {
- sb.append(mContext.getText(
- com.android.internal.R.string.badPuk));
+ if (isPinPukCommand()) {
+ // look specifically for the PUK commands and adjust
+ // the message accordingly.
+ if (mSc.equals(SC_PUK) || mSc.equals(SC_PUK2)) {
+ sb.append(mContext.getText(
+ com.android.internal.R.string.badPuk));
+ } else {
+ sb.append(mContext.getText(
+ com.android.internal.R.string.badPin));
+ }
+ // Get the No. of retries remaining to unlock PUK/PUK2
+ int attemptsRemaining = msg.arg1;
+ if (attemptsRemaining <= 0) {
+ Rlog.d(LOG_TAG, "onSetComplete: PUK locked,"
+ + " cancel as lock screen will handle this");
+ mState = State.CANCELLED;
+ } else if (attemptsRemaining > 0) {
+ Rlog.d(LOG_TAG, "onSetComplete: attemptsRemaining="+attemptsRemaining);
+ sb.append(mContext.getResources().getQuantityString(
+ com.android.internal.R.plurals.pinpuk_attempts,
+ attemptsRemaining, attemptsRemaining));
+ }
} else {
sb.append(mContext.getText(
com.android.internal.R.string.passwordIncorrect));
}
+ } else if (err == CommandException.Error.SIM_PUK2) {
+ sb.append(mContext.getText(
+ com.android.internal.R.string.badPin));
+ sb.append("\n");
+ sb.append(mContext.getText(
+ com.android.internal.R.string.needPuk2));
+ } else if (err == CommandException.Error.REQUEST_NOT_SUPPORTED) {
+ if (mSc.equals(SC_PIN)) {
+ sb.append(mContext.getText(com.android.internal.R.string.enablePin));
+ }
} else {
sb.append(mContext.getText(
com.android.internal.R.string.mmiError));
diff --git a/src/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java b/src/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
index 147a310..f168180 100755
--- a/src/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
+++ b/src/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,12 +27,11 @@
import android.telephony.SmsManager;
import com.android.internal.telephony.GsmAlphabet;
-import com.android.internal.telephony.SmsConstants;
+import com.android.internal.telephony.ImsSMSDispatcher;
import com.android.internal.telephony.PhoneBase;
import com.android.internal.telephony.SMSDispatcher;
-import com.android.internal.telephony.ImsSMSDispatcher;
+import com.android.internal.telephony.SmsConstants;
import com.android.internal.telephony.SmsHeader;
-import com.android.internal.telephony.SmsStorageMonitor;
import com.android.internal.telephony.SmsUsageMonitor;
import com.android.internal.telephony.TelephonyProperties;
import com.android.internal.telephony.cdma.sms.UserData;
@@ -43,15 +41,18 @@
public class CdmaSMSDispatcher extends SMSDispatcher {
private static final String TAG = "CdmaSMSDispatcher";
private static final boolean VDBG = false;
- private ImsSMSDispatcher mImsSMSDispatcher;
- public CdmaSMSDispatcher(PhoneBase phone, SmsStorageMonitor storageMonitor,
- SmsUsageMonitor usageMonitor, ImsSMSDispatcher imsSMSDispatcher) {
- super(phone, usageMonitor);
- mImsSMSDispatcher = imsSMSDispatcher;
+ public CdmaSMSDispatcher(PhoneBase phone, SmsUsageMonitor usageMonitor,
+ ImsSMSDispatcher imsSMSDispatcher) {
+ super(phone, usageMonitor, imsSMSDispatcher);
Rlog.d(TAG, "CdmaSMSDispatcher created");
}
+ @Override
+ protected String getFormat() {
+ return SmsConstants.FORMAT_3GPP2;
+ }
+
/**
* Send the SMS status report to the dispatcher thread to process.
* @param sms the CDMA SMS message containing the status report
@@ -71,10 +72,6 @@
}
}
- protected String getFormat() {
- return SmsConstants.FORMAT_3GPP2;
- }
-
/**
* Called from parent class to handle status report from {@code CdmaInboundSmsHandler}.
* @param sms the CDMA SMS message to process
@@ -106,8 +103,8 @@
byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(
scAddr, destAddr, destPort, data, (deliveryIntent != null));
- HashMap map = SmsTrackerMapFactory(destAddr, scAddr, destPort, data, pdu);
- SmsTracker tracker = SmsTrackerFactory(map, sentIntent, deliveryIntent,
+ HashMap map = getSmsTrackerMap(destAddr, scAddr, destPort, data, pdu);
+ SmsTracker tracker = getSmsTracker(map, sentIntent, deliveryIntent,
getFormat());
sendSubmitPdu(tracker);
}
@@ -118,8 +115,8 @@
PendingIntent sentIntent, PendingIntent deliveryIntent) {
SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(
scAddr, destAddr, text, (deliveryIntent != null), null);
- HashMap map = SmsTrackerMapFactory(destAddr, scAddr, text, pdu);
- SmsTracker tracker = SmsTrackerFactory(map, sentIntent,
+ HashMap map = getSmsTrackerMap(destAddr, scAddr, text, pdu);
+ SmsTracker tracker = getSmsTracker(map, sentIntent,
deliveryIntent, getFormat());
sendSubmitPdu(tracker);
}
@@ -153,9 +150,9 @@
SmsMessage.SubmitPdu submitPdu = SmsMessage.getSubmitPdu(destinationAddress,
uData, (deliveryIntent != null) && lastPart);
- HashMap map = SmsTrackerMapFactory(destinationAddress, scAddress,
+ HashMap map = getSmsTrackerMap(destinationAddress, scAddress,
message, submitPdu);
- SmsTracker tracker = SmsTrackerFactory(map, sentIntent,
+ SmsTracker tracker = getSmsTracker(map, sentIntent,
deliveryIntent, getFormat());
sendSubmitPdu(tracker);
}
@@ -205,20 +202,4 @@
tracker.mImsRetry++;
}
}
-
- @Override
- public void sendRetrySms(SmsTracker tracker) {
- //re-routing to ImsSMSDispatcher
- mImsSMSDispatcher.sendRetrySms(tracker);
- }
-
- @Override
- public boolean isIms() {
- return mImsSMSDispatcher.isIms();
- }
-
- @Override
- public String getImsSmsFormat() {
- return mImsSMSDispatcher.getImsSmsFormat();
- }
}
diff --git a/src/java/com/android/internal/telephony/cdma/CdmaServiceCategoryProgramHandler.java b/src/java/com/android/internal/telephony/cdma/CdmaServiceCategoryProgramHandler.java
index f11c681..bb9f9d5 100644
--- a/src/java/com/android/internal/telephony/cdma/CdmaServiceCategoryProgramHandler.java
+++ b/src/java/com/android/internal/telephony/cdma/CdmaServiceCategoryProgramHandler.java
@@ -45,14 +45,13 @@
*/
public final class CdmaServiceCategoryProgramHandler extends WakeLockStateMachine {
- private final Context mContext;
final CommandsInterface mCi;
/**
* Create a new CDMA inbound SMS handler.
*/
CdmaServiceCategoryProgramHandler(Context context, CommandsInterface commandsInterface) {
- super("CdmaServiceCategoryProgramHandler", context);
+ super("CdmaServiceCategoryProgramHandler", context, null);
mContext = context;
mCi = commandsInterface;
}
@@ -159,7 +158,7 @@
dos.writeInt(0); //servicePresent
dos.writeInt(0); //serviceCategory
CdmaSmsAddress destAddr = CdmaSmsAddress.parse(
- PhoneNumberUtils.cdmaCheckAndProcessPlusCode(sender));
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCodeForSms(sender));
dos.write(destAddr.digitMode);
dos.write(destAddr.numberMode);
dos.write(destAddr.ton); // number_type
diff --git a/src/java/com/android/internal/telephony/cdma/SmsMessage.java b/src/java/com/android/internal/telephony/cdma/SmsMessage.java
index 8459aca..2d5dda7 100644
--- a/src/java/com/android/internal/telephony/cdma/SmsMessage.java
+++ b/src/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -856,7 +855,7 @@
* Convert + code to 011 and dial out for international SMS
*/
CdmaSmsAddress destAddr = CdmaSmsAddress.parse(
- PhoneNumberUtils.cdmaCheckAndProcessPlusCode(destAddrStr));
+ PhoneNumberUtils.cdmaCheckAndProcessPlusCodeForSms(destAddrStr));
if (destAddr == null) return null;
BearerData bearerData = new BearerData();
diff --git a/src/java/com/android/internal/telephony/dataconnection/ApnContext.java b/src/java/com/android/internal/telephony/dataconnection/ApnContext.java
index 312d033..16aad87 100644
--- a/src/java/com/android/internal/telephony/dataconnection/ApnContext.java
+++ b/src/java/com/android/internal/telephony/dataconnection/ApnContext.java
@@ -18,6 +18,7 @@
import android.app.PendingIntent;
import android.content.Context;
+import android.net.NetworkConfig;
import android.telephony.Rlog;
import com.android.internal.R;
@@ -47,6 +48,8 @@
private ArrayList<ApnSetting> mWaitingApns = null;
+ public final int priority;
+
/** A zero indicates that all waiting APNs had a permanent error */
private AtomicInteger mWaitingApnsPermanentFailureCountDown;
@@ -68,14 +71,15 @@
*/
AtomicBoolean mDependencyMet;
- public ApnContext(Context context, String apnType, String logTag) {
+ public ApnContext(Context context, String apnType, String logTag, NetworkConfig config) {
mContext = context;
mApnType = apnType;
mState = DctConstants.State.IDLE;
setReason(Phone.REASON_DATA_ENABLED);
mDataEnabled = new AtomicBoolean(false);
- mDependencyMet = new AtomicBoolean(true);
+ mDependencyMet = new AtomicBoolean(config.dependencyMet);
mWaitingApnsPermanentFailureCountDown = new AtomicInteger(0);
+ priority = config.priority;
LOG_TAG = logTag;
}
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
index 517cb92..9cfed88 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
@@ -1197,7 +1197,6 @@
+ "RefCount=" + mApnContexts.size());
}
mInactiveState.setEnterNotificationParams(DcFailCause.LOST_CONNECTION);
- deferMessage(msg);
transitionTo(mInactiveState);
retVal = HANDLED;
break;
@@ -1474,7 +1473,6 @@
log("DcActiveState EVENT_DISCONNECT clearing apn contexts,"
+ " dc=" + DataConnection.this);
}
- mApnContexts.clear();
DisconnectParams dp = (DisconnectParams) msg.obj;
mDisconnectParams = dp;
mConnectionParams = null;
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
index 2db30f9..9e6140f 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
@@ -35,6 +35,7 @@
import android.net.ProxyProperties;
import android.net.Uri;
import android.os.AsyncResult;
+import android.os.Build;
import android.os.Message;
import android.os.Messenger;
import android.os.SystemClock;
@@ -190,6 +191,7 @@
mPhone.getContext().getContentResolver().unregisterContentObserver(mApnObserver);
mApnContexts.clear();
+ mPrioritySortedApnContexts.clear();
destroyDataConnections();
}
@@ -230,9 +232,9 @@
}
private ApnContext addApnContext(String type, NetworkConfig networkConfig) {
- ApnContext apnContext = new ApnContext(mPhone.getContext(), type, LOG_TAG);
- apnContext.setDependencyMet(networkConfig.dependencyMet);
+ ApnContext apnContext = new ApnContext(mPhone.getContext(), type, LOG_TAG, networkConfig);
mApnContexts.put(type, apnContext);
+ mPrioritySortedApnContexts.add(apnContext);
return apnContext;
}
@@ -596,7 +598,10 @@
}
private void setupDataOnConnectableApns(String reason) {
- for (ApnContext apnContext : mApnContexts.values()) {
+ if (DBG) log("setupDataOnConnectableApns: " + reason);
+
+ for (ApnContext apnContext : mPrioritySortedApnContexts) {
+ if (DBG) log("setupDataOnConnectableApns: apnContext " + apnContext);
if (apnContext.getState() == DctConstants.State.FAILED) {
apnContext.setState(DctConstants.State.IDLE);
}
@@ -608,28 +613,6 @@
}
}
- private boolean trySetupData(String reason, String type) {
- if (DBG) {
- log("trySetupData: " + type + " due to " + (reason == null ? "(unspecified)" : reason)
- + " isPsRestricted=" + mIsPsRestricted);
- }
-
- if (type == null) {
- type = PhoneConstants.APN_TYPE_DEFAULT;
- }
-
- ApnContext apnContext = mApnContexts.get(type);
-
- if (apnContext == null ){
- if (DBG) log("trySetupData new apn context for type:" + type);
- apnContext = new ApnContext(mPhone.getContext(), type, LOG_TAG);
- mApnContexts.put(type, apnContext);
- }
- apnContext.setReason(reason);
-
- return trySetupData(apnContext);
- }
-
private boolean trySetupData(ApnContext apnContext) {
if (DBG) {
log("trySetupData for type:" + apnContext.getApnType() +
@@ -720,11 +703,16 @@
* @param tearDown true if the underlying DataConnection should be
* disconnected.
* @param reason reason for the clean up.
+ * @return boolean - true if we did cleanup any connections, false if they
+ * were already all disconnected.
*/
- protected void cleanUpAllConnections(boolean tearDown, String reason) {
+ protected boolean cleanUpAllConnections(boolean tearDown, String reason) {
if (DBG) log("cleanUpAllConnections: tearDown=" + tearDown + " reason=" + reason);
+ boolean didDisconnect = false;
for (ApnContext apnContext : mApnContexts.values()) {
+ if (apnContext.isDisconnected() == false) didDisconnect = true;
+ // TODO - only do cleanup if not disconnected
apnContext.setReason(reason);
cleanUpConnection(tearDown, apnContext);
}
@@ -734,6 +722,7 @@
// TODO: Do we need mRequestedApnType?
mRequestedApnType = PhoneConstants.APN_TYPE_DEFAULT;
+ return didDisconnect;
}
/**
@@ -1033,6 +1022,29 @@
}
}
if (dcac == null) {
+ if (isOnlySingleDcAllowed(radioTech)) {
+ if (isHigherPriorityApnContextActive(apnContext)) {
+ if (DBG) {
+ log("setupData: Higher priority ApnContext active. Ignoring call");
+ }
+ return false;
+ }
+
+ // Only lower priority calls left. Disconnect them all in this single PDP case
+ // so that we can bring up the requested higher priority call (once we receive
+ // repsonse for deactivate request for the calls we are about to disconnect
+ if (cleanUpAllConnections(true, Phone.REASON_SINGLE_PDN_ARBITRATION)) {
+ // If any call actually requested to be disconnected, means we can't
+ // bring up this connection yet as we need to wait for those data calls
+ // to be disconnected.
+ if (DBG) log("setupData: Some calls are disconnecting first. Wait and retry");
+ return false;
+ }
+
+ // No other calls are active, so proceed
+ if (DBG) log("setupData: Single pdp. Continue setting up data call.");
+ }
+
dcac = findFreeDataConnection();
if (dcac == null) {
@@ -1166,6 +1178,45 @@
mActiveApn = null;
}
+ /**
+ * "Active" here means ApnContext isEnabled() and not in FAILED state
+ * @param apnContext to compare with
+ * @return true if higher priority active apn found
+ */
+ private boolean isHigherPriorityApnContextActive(ApnContext apnContext) {
+ for (ApnContext otherContext : mPrioritySortedApnContexts) {
+ if (apnContext.getApnType().equalsIgnoreCase(otherContext.getApnType())) return false;
+ if (otherContext.isEnabled() && otherContext.getState() != DctConstants.State.FAILED) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Reports if we support multiple connections or not.
+ * This is a combination of factors, based on carrier and RAT.
+ * @param rilRadioTech the RIL Radio Tech currently in use
+ * @return true if only single DataConnection is allowed
+ */
+ private boolean isOnlySingleDcAllowed(int rilRadioTech) {
+ int[] singleDcRats = mPhone.getContext().getResources().getIntArray(
+ com.android.internal.R.array.config_onlySingleDcAllowed);
+ boolean onlySingleDcAllowed = false;
+ if (Build.IS_DEBUGGABLE &&
+ SystemProperties.getBoolean("persist.telephony.test.singleDc", false)) {
+ onlySingleDcAllowed = true;
+ }
+ if (singleDcRats != null) {
+ for (int i=0; i < singleDcRats.length && onlySingleDcAllowed == false; i++) {
+ if (rilRadioTech == singleDcRats[i]) onlySingleDcAllowed = true;
+ }
+ }
+
+ if (DBG) log("isOnlySingleDcAllowed(" + rilRadioTech + "): " + onlySingleDcAllowed);
+ return onlySingleDcAllowed;
+ }
+
@Override
protected void restartRadio() {
if (DBG) log("restartRadio: ************TURN OFF RADIO**************");
@@ -1190,10 +1241,13 @@
* @param reason the reason why data is disconnected
* @return true if try setup data connection is need for this reason
*/
- private boolean retryAfterDisconnected(String reason) {
+ private boolean retryAfterDisconnected(ApnContext apnContext) {
boolean retry = true;
+ String reason = apnContext.getReason();
- if ( Phone.REASON_RADIO_TURNED_OFF.equals(reason) ) {
+ if ( Phone.REASON_RADIO_TURNED_OFF.equals(reason) ||
+ (isOnlySingleDcAllowed(mPhone.getServiceState().getRilDataRadioTechnology())
+ && isHigherPriorityApnContextActive(apnContext))) {
retry = false;
}
return retry;
@@ -1505,8 +1559,9 @@
log("completeConnection: MOBILE_PROVISIONING_ACTION url="
+ mProvisioningUrl);
}
- Intent newIntent =
- new Intent(Intent.ACTION_VIEW, Uri.parse(mProvisioningUrl));
+ Intent newIntent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN,
+ Intent.CATEGORY_APP_BROWSER);
+ newIntent.setData(Uri.parse(mProvisioningUrl));
newIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT |
Intent.FLAG_ACTIVITY_NEW_TASK);
try {
@@ -1755,6 +1810,7 @@
// pending.
if (isDisconnected()) {
if (mPhone.getServiceStateTracker().processPendingRadioPowerOffAfterDataOff()) {
+ if(DBG) log("onDisconnectDone: radio will be turned off, no retries");
// Radio will be turned off. No need to retry data setup
apnContext.setApnSetting(null);
apnContext.setDataConnectionAc(null);
@@ -1763,16 +1819,29 @@
}
// If APN is still enabled, try to bring it back up automatically
- if (mAttached.get() && apnContext.isReady()
- && retryAfterDisconnected(apnContext.getReason())) {
+ if (mAttached.get() && apnContext.isReady() && retryAfterDisconnected(apnContext)) {
SystemProperties.set(PUPPET_MASTER_RADIO_STRESS_TEST, "false");
// Wait a bit before trying the next APN, so that
// we're not tying up the RIL command channel.
// This also helps in any external dependency to turn off the context.
+ if(DBG) log("onDisconnectDone: attached, ready and retry after disconnect");
startAlarmForReconnect(getApnDelay(), apnContext);
} else {
+ boolean restartRadioAfterProvisioning = mPhone.getContext().getResources().getBoolean(
+ com.android.internal.R.bool.config_restartRadioAfterProvisioning);
+
+ if (apnContext.isProvisioningApn() && restartRadioAfterProvisioning) {
+ log("onDisconnectDone: restartRadio after provisioning");
+ restartRadio();
+ }
apnContext.setApnSetting(null);
apnContext.setDataConnectionAc(null);
+ if (isOnlySingleDcAllowed(mPhone.getServiceState().getRilDataRadioTechnology())) {
+ if(DBG) log("onDisconnectDone: isOnlySigneDcAllowed true so setup single apn");
+ setupDataOnConnectableApns(Phone.REASON_SINGLE_PDN_ARBITRATION);
+ } else {
+ if(DBG) log("onDisconnectDone: not retrying");
+ }
}
}
@@ -2182,7 +2251,16 @@
cleanUpAllConnections(false, Phone.REASON_PS_RESTRICT_ENABLED);
mReregisterOnReconnectFailure = false;
}
- trySetupData(Phone.REASON_PS_RESTRICT_ENABLED, PhoneConstants.APN_TYPE_DEFAULT);
+ ApnContext apnContext = mApnContexts.get(PhoneConstants.APN_TYPE_DEFAULT);
+ if (apnContext != null) {
+ apnContext.setReason(Phone.REASON_PS_RESTRICT_ENABLED);
+ trySetupData(apnContext);
+ } else {
+ loge("**** Default ApnContext not found ****");
+ if (Build.IS_DEBUGGABLE) {
+ throw new RuntimeException("Default ApnContext not found");
+ }
+ }
}
break;
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcTrackerBase.java b/src/java/com/android/internal/telephony/dataconnection/DcTrackerBase.java
index 9e7702e..a8050a6 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcTrackerBase.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcTrackerBase.java
@@ -63,12 +63,14 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
+import java.util.PriorityQueue;
/**
* {@hide}
@@ -251,9 +253,19 @@
new HashMap<String, Integer>();
/** Phone.APN_TYPE_* ===> ApnContext */
- protected ConcurrentHashMap<String, ApnContext> mApnContexts =
+ protected final ConcurrentHashMap<String, ApnContext> mApnContexts =
new ConcurrentHashMap<String, ApnContext>();
+ /** kept in sync with mApnContexts
+ * Higher numbers are higher priority and sorted so highest priority is first */
+ protected final PriorityQueue<ApnContext>mPrioritySortedApnContexts =
+ new PriorityQueue<ApnContext>(5,
+ new Comparator<ApnContext>() {
+ public int compare(ApnContext c1, ApnContext c2) {
+ return c2.priority - c1.priority;
+ }
+ } );
+
/* Currently active APN */
protected ApnSetting mActiveApn;
@@ -604,8 +616,12 @@
Settings.Global.TETHER_DUN_APN);
ApnSetting dunSetting = ApnSetting.fromString(apnData);
if (dunSetting != null) {
- if (VDBG) log("fetchDunApn: global TETHER_DUN_APN dunSetting=" + dunSetting);
- return dunSetting;
+ IccRecords r = mIccRecords.get();
+ String operator = (r != null) ? r.getOperatorNumeric() : "";
+ if (dunSetting.numeric.equals(operator)) {
+ if (VDBG) log("fetchDunApn: global TETHER_DUN_APN dunSetting=" + dunSetting);
+ return dunSetting;
+ }
}
apnData = c.getResources().getString(R.string.config_tether_apndata);
diff --git a/src/java/com/android/internal/telephony/gsm/GSMPhone.java b/src/java/com/android/internal/telephony/gsm/GSMPhone.java
index 97cf994..2b435b5 100644
--- a/src/java/com/android/internal/telephony/gsm/GSMPhone.java
+++ b/src/java/com/android/internal/telephony/gsm/GSMPhone.java
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2006 The Android Open Source Project
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -119,8 +118,6 @@
private String mImeiSv;
private String mVmNumber;
- GsmInboundSmsHandler mGsmInboundSmsHandler;
-
// Create Cfu (Call forward unconditional) so that dialling number &
// mOnComplete (Message object passed by client) can be packed &
// given as a single Cfu object as user data to RIL.
@@ -216,7 +213,12 @@
@Override
public ServiceState
getServiceState() {
- return mSST.mSS;
+ if (mSST != null) {
+ return mSST.mSS;
+ } else {
+ // avoid potential NPE in EmergencyCallHelper during Phone switch
+ return new ServiceState();
+ }
}
@Override
@@ -714,7 +716,7 @@
public boolean handlePinMmi(String dialString) {
GsmMmiCode mmi = GsmMmiCode.newFromDialString(dialString, this, mUiccApplication.get());
- if (mmi != null && mmi.isPinCommand()) {
+ if (mmi != null && mmi.isPinPukCommand()) {
mPendingMMIs.add(mmi);
mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
mmi.processCode();
diff --git a/src/java/com/android/internal/telephony/gsm/GsmCellBroadcastHandler.java b/src/java/com/android/internal/telephony/gsm/GsmCellBroadcastHandler.java
index de98458..6671a58 100644
--- a/src/java/com/android/internal/telephony/gsm/GsmCellBroadcastHandler.java
+++ b/src/java/com/android/internal/telephony/gsm/GsmCellBroadcastHandler.java
@@ -42,11 +42,8 @@
private final HashMap<SmsCbConcatInfo, byte[][]> mSmsCbPageMap =
new HashMap<SmsCbConcatInfo, byte[][]>(4);
- private final PhoneBase mPhone;
-
protected GsmCellBroadcastHandler(Context context, PhoneBase phone) {
- super("GsmCellBroadcastHandler", context);
- mPhone = phone;
+ super("GsmCellBroadcastHandler", context, phone);
phone.mCi.setOnNewGsmBroadcastSms(getHandler(), EVENT_NEW_SMS_MESSAGE, null);
}
diff --git a/src/java/com/android/internal/telephony/gsm/GsmInboundSmsHandler.java b/src/java/com/android/internal/telephony/gsm/GsmInboundSmsHandler.java
index 2c63bf0..7e48cc2 100644
--- a/src/java/com/android/internal/telephony/gsm/GsmInboundSmsHandler.java
+++ b/src/java/com/android/internal/telephony/gsm/GsmInboundSmsHandler.java
@@ -38,20 +38,14 @@
/** Handler for SMS-PP data download messages to UICC. */
private final UsimDataDownloadHandler mDataDownloadHandler;
- private final GsmCellBroadcastHandler mCellBroadcastDispatcher;
-
- private final PhoneBase mPhone;
-
/**
* Create a new GSM inbound SMS handler.
*/
private GsmInboundSmsHandler(Context context, SmsStorageMonitor storageMonitor,
PhoneBase phone) {
- super("GsmInboundSmsHandler", context, storageMonitor);
- mPhone = phone;
+ super("GsmInboundSmsHandler", context, storageMonitor, phone,
+ GsmCellBroadcastHandler.makeGsmCellBroadcastHandler(context, phone));
phone.mCi.setOnNewGsmSms(getHandler(), EVENT_NEW_SMS, null);
- mCellBroadcastDispatcher = GsmCellBroadcastHandler.makeGsmCellBroadcastHandler(context,
- phone);
mDataDownloadHandler = new UsimDataDownloadHandler(phone.mCi);
}
@@ -61,7 +55,7 @@
@Override
protected void onQuitting() {
mPhone.mCi.unSetOnNewGsmSms(getHandler());
- mCellBroadcastDispatcher.dispose();
+ mCellBroadcastHandler.dispose();
if (DBG) log("unregistered for 3GPP SMS");
super.onQuitting(); // release wakelock
@@ -147,6 +141,22 @@
}
/**
+ * Called when the phone changes the default method updates mPhone
+ * mStorageMonitor and mCellBroadcastHandler.updatePhoneObject.
+ * Override if different or other behavior is desired.
+ *
+ * @param phone
+ */
+ @Override
+ protected void onUpdatePhoneObject(PhoneBase phone) {
+ super.onUpdatePhoneObject(phone);
+ log("onUpdatePhoneObject: dispose of old CellBroadcastHandler and make a new one");
+ mCellBroadcastHandler.dispose();
+ mCellBroadcastHandler = GsmCellBroadcastHandler
+ .makeGsmCellBroadcastHandler(mContext, phone);
+ }
+
+ /**
* Convert Android result code to 3GPP SMS failure cause.
* @param rc the Android SMS intent result value
* @return 0 for success, or a 3GPP SMS failure cause value
diff --git a/src/java/com/android/internal/telephony/gsm/GsmMmiCode.java b/src/java/com/android/internal/telephony/gsm/GsmMmiCode.java
index f41391d..c2bafbe 100644
--- a/src/java/com/android/internal/telephony/gsm/GsmMmiCode.java
+++ b/src/java/com/android/internal/telephony/gsm/GsmMmiCode.java
@@ -564,7 +564,7 @@
/**
* @return true if the Service Code is PIN/PIN2/PUK/PUK2-related
*/
- boolean isPinCommand() {
+ boolean isPinPukCommand() {
return mSc != null && (mSc.equals(SC_PIN) || mSc.equals(SC_PIN2)
|| mSc.equals(SC_PUK) || mSc.equals(SC_PUK2));
}
@@ -779,43 +779,53 @@
} else {
throw new RuntimeException ("Invalid or Unsupported MMI Code");
}
- } else if (isPinCommand()) {
+ } else if (isPinPukCommand()) {
+ // TODO: This is the same as the code in CmdaMmiCode.java,
+ // MmiCode should be an abstract or base class and this and
+ // other common variables and code should be promoted.
+
// sia = old PIN or PUK
// sib = new PIN
// sic = new PIN
String oldPinOrPuk = mSia;
- String newPin = mSib;
- int pinLen = newPin.length();
+ String newPinOrPuk = mSib;
+ int pinLen = newPinOrPuk.length();
if (isRegister()) {
- if (!newPin.equals(mSic)) {
+ if (!newPinOrPuk.equals(mSic)) {
// password mismatch; return error
handlePasswordError(com.android.internal.R.string.mismatchPin);
} else if (pinLen < 4 || pinLen > 8 ) {
// invalid length
handlePasswordError(com.android.internal.R.string.invalidPin);
- } else if (mSc.equals(SC_PIN) &&
- mUiccApplication != null &&
- mUiccApplication.getState() == AppState.APPSTATE_PUK ) {
+ } else if (mSc.equals(SC_PIN)
+ && mUiccApplication != null
+ && mUiccApplication.getState() == AppState.APPSTATE_PUK) {
// Sim is puk-locked
handlePasswordError(com.android.internal.R.string.needPuk);
- } else {
- // pre-checks OK
+ } else if (mUiccApplication != null) {
+ Rlog.d(LOG_TAG, "process mmi service code using UiccApp sc=" + mSc);
+
+ // We have an app and the pre-checks are OK
if (mSc.equals(SC_PIN)) {
- mPhone.mCi.changeIccPin(oldPinOrPuk, newPin,
+ mUiccApplication.changeIccLockPassword(oldPinOrPuk, newPinOrPuk,
obtainMessage(EVENT_SET_COMPLETE, this));
} else if (mSc.equals(SC_PIN2)) {
- mPhone.mCi.changeIccPin2(oldPinOrPuk, newPin,
+ mUiccApplication.changeIccFdnPassword(oldPinOrPuk, newPinOrPuk,
obtainMessage(EVENT_SET_COMPLETE, this));
} else if (mSc.equals(SC_PUK)) {
- mPhone.mCi.supplyIccPuk(oldPinOrPuk, newPin,
+ mUiccApplication.supplyPuk(oldPinOrPuk, newPinOrPuk,
obtainMessage(EVENT_SET_COMPLETE, this));
} else if (mSc.equals(SC_PUK2)) {
- mPhone.mCi.supplyIccPuk2(oldPinOrPuk, newPin,
+ mUiccApplication.supplyPuk2(oldPinOrPuk, newPinOrPuk,
obtainMessage(EVENT_SET_COMPLETE, this));
+ } else {
+ throw new RuntimeException("uicc unsupported service code=" + mSc);
}
+ } else {
+ throw new RuntimeException("No application mUiccApplicaiton is null");
}
} else {
- throw new RuntimeException ("Invalid or Unsupported MMI Code");
+ throw new RuntimeException ("Ivalid register/action=" + mAction);
}
} else if (mPoundString != null) {
sendUssd(mPoundString);
@@ -904,7 +914,7 @@
case EVENT_SET_COMPLETE:
ar = (AsyncResult) (msg.obj);
- onSetComplete(ar);
+ onSetComplete(msg, ar);
break;
case EVENT_SET_CFF_COMPLETE:
@@ -921,7 +931,7 @@
}
}
- onSetComplete(ar);
+ onSetComplete(msg, ar);
break;
case EVENT_GET_CLIR_COMPLETE:
@@ -990,7 +1000,7 @@
return mContext.getText(com.android.internal.R.string.PwdMmi);
} else if (mSc.equals(SC_WAIT)) {
return mContext.getText(com.android.internal.R.string.CwMmi);
- } else if (isPinCommand()) {
+ } else if (isPinPukCommand()) {
return mContext.getText(com.android.internal.R.string.PinMmi);
}
}
@@ -999,7 +1009,7 @@
}
private void
- onSetComplete(AsyncResult ar){
+ onSetComplete(Message msg, AsyncResult ar){
StringBuilder sb = new StringBuilder(getScString());
sb.append("\n");
@@ -1008,7 +1018,7 @@
if (ar.exception instanceof CommandException) {
CommandException.Error err = ((CommandException)(ar.exception)).getCommandError();
if (err == CommandException.Error.PASSWORD_INCORRECT) {
- if (isPinCommand()) {
+ if (isPinPukCommand()) {
// look specifically for the PUK commands and adjust
// the message accordingly.
if (mSc.equals(SC_PUK) || mSc.equals(SC_PUK2)) {
@@ -1018,6 +1028,18 @@
sb.append(mContext.getText(
com.android.internal.R.string.badPin));
}
+ // Get the No. of retries remaining to unlock PUK/PUK2
+ int attemptsRemaining = msg.arg1;
+ if (attemptsRemaining <= 0) {
+ Rlog.d(LOG_TAG, "onSetComplete: PUK locked,"
+ + " cancel as lock screen will handle this");
+ mState = State.CANCELLED;
+ } else if (attemptsRemaining > 0) {
+ Rlog.d(LOG_TAG, "onSetComplete: attemptsRemaining="+attemptsRemaining);
+ sb.append(mContext.getResources().getQuantityString(
+ com.android.internal.R.plurals.pinpuk_attempts,
+ attemptsRemaining, attemptsRemaining));
+ }
} else {
sb.append(mContext.getText(
com.android.internal.R.string.passwordIncorrect));
@@ -1028,6 +1050,10 @@
sb.append("\n");
sb.append(mContext.getText(
com.android.internal.R.string.needPuk2));
+ } else if (err == CommandException.Error.REQUEST_NOT_SUPPORTED) {
+ if (mSc.equals(SC_PIN)) {
+ sb.append(mContext.getText(com.android.internal.R.string.enablePin));
+ }
} else if (err == CommandException.Error.FDN_CHECK_FAILURE) {
Rlog.i(LOG_TAG, "FDN_CHECK_FAILURE");
sb.append(mContext.getText(com.android.internal.R.string.mmiFdnError));
diff --git a/src/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java b/src/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
index 4520d70..345abba 100644
--- a/src/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
+++ b/src/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2006 The Android Open Source Project
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,11 +27,11 @@
import android.telephony.Rlog;
import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.ImsSMSDispatcher;
+import com.android.internal.telephony.InboundSmsHandler;
import com.android.internal.telephony.PhoneBase;
import com.android.internal.telephony.SMSDispatcher;
import com.android.internal.telephony.SmsConstants;
-import com.android.internal.telephony.ImsSMSDispatcher;
-import com.android.internal.telephony.InboundSmsHandler;
import com.android.internal.telephony.SmsHeader;
import com.android.internal.telephony.SmsStorageMonitor;
import com.android.internal.telephony.SmsUsageMonitor;
@@ -51,7 +50,6 @@
public final class GsmSMSDispatcher extends SMSDispatcher {
private static final String TAG = "GsmSMSDispatcher";
private static final boolean VDBG = false;
- private ImsSMSDispatcher mImsSMSDispatcher;
protected UiccController mUiccController = null;
private AtomicReference<IccRecords> mIccRecords = new AtomicReference<IccRecords>();
private AtomicReference<UiccCardApplication> mUiccApplication =
@@ -61,13 +59,14 @@
/** Status report received */
private static final int EVENT_NEW_SMS_STATUS_REPORT = 100;
- public GsmSMSDispatcher(PhoneBase phone, SmsStorageMonitor storageMonitor,
- SmsUsageMonitor usageMonitor, ImsSMSDispatcher imsSMSDispatcher,
+ public GsmSMSDispatcher(PhoneBase phone, SmsUsageMonitor usageMonitor,
+ ImsSMSDispatcher imsSMSDispatcher,
GsmInboundSmsHandler gsmInboundSmsHandler) {
- super(phone, usageMonitor);
+ super(phone, usageMonitor, imsSMSDispatcher);
mCi.setOnSmsStatus(this, EVENT_NEW_SMS_STATUS_REPORT, null);
- mImsSMSDispatcher = imsSMSDispatcher;
mGsmInboundSmsHandler = gsmInboundSmsHandler;
+ mUiccController = UiccController.getInstance();
+ mUiccController.registerForIccChanged(this, EVENT_ICC_CHANGED, null);
Rlog.d(TAG, "GsmSMSDispatcher created");
}
@@ -75,6 +74,7 @@
public void dispose() {
super.dispose();
mCi.unSetOnSmsStatus(this);
+ mUiccController.unregisterForIccChanged(this);
}
@Override
@@ -155,8 +155,8 @@
SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(
scAddr, destAddr, destPort, data, (deliveryIntent != null));
if (pdu != null) {
- HashMap map = SmsTrackerMapFactory(destAddr, scAddr, destPort, data, pdu);
- SmsTracker tracker = SmsTrackerFactory(map, sentIntent, deliveryIntent,
+ HashMap map = getSmsTrackerMap(destAddr, scAddr, destPort, data, pdu);
+ SmsTracker tracker = getSmsTracker(map, sentIntent, deliveryIntent,
getFormat());
sendRawPdu(tracker);
} else {
@@ -171,8 +171,8 @@
SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(
scAddr, destAddr, text, (deliveryIntent != null));
if (pdu != null) {
- HashMap map = SmsTrackerMapFactory(destAddr, scAddr, text, pdu);
- SmsTracker tracker = SmsTrackerFactory(map, sentIntent, deliveryIntent,
+ HashMap map = getSmsTrackerMap(destAddr, scAddr, text, pdu);
+ SmsTracker tracker = getSmsTracker(map, sentIntent, deliveryIntent,
getFormat());
sendRawPdu(tracker);
} else {
@@ -196,9 +196,9 @@
message, deliveryIntent != null, SmsHeader.toByteArray(smsHeader),
encoding, smsHeader.languageTable, smsHeader.languageShiftTable);
if (pdu != null) {
- HashMap map = SmsTrackerMapFactory(destinationAddress, scAddress,
+ HashMap map = getSmsTrackerMap(destinationAddress, scAddress,
message, pdu);
- SmsTracker tracker = SmsTrackerFactory(map, sentIntent,
+ SmsTracker tracker = getSmsTracker(map, sentIntent,
deliveryIntent, getFormat());
sendRawPdu(tracker);
} else {
@@ -263,12 +263,6 @@
}
}
- @Override
- public void sendRetrySms(SmsTracker tracker) {
- //re-routing to ImsSMSDispatcher
- mImsSMSDispatcher.sendRetrySms(tracker);
- }
-
protected UiccCardApplication getUiccCardApplication() {
return mUiccController.getUiccCardApplication(UiccController.APP_FAM_3GPP);
}
@@ -300,14 +294,4 @@
}
}
}
-
- @Override
- public boolean isIms() {
- return mImsSMSDispatcher.isIms();
- }
-
- @Override
- public String getImsSmsFormat() {
- return mImsSMSDispatcher.getImsSmsFormat();
- }
}
diff --git a/src/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/src/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
index 5884aeb..0b75d49 100644
--- a/src/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
@@ -1367,8 +1367,6 @@
for (String numeric : numericArray) {
if (operatorNumeric.startsWith(numeric))
return true;
- else
- return false;
}
return false;
}
diff --git a/src/java/com/android/internal/telephony/gsm/SmsMessage.java b/src/java/com/android/internal/telephony/gsm/SmsMessage.java
index 6d5ecd9..48d76c5 100644
--- a/src/java/com/android/internal/telephony/gsm/SmsMessage.java
+++ b/src/java/com/android/internal/telephony/gsm/SmsMessage.java
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2006 The Android Open Source Project
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -558,8 +557,9 @@
try {
ret = new GsmSmsAddress(mPdu, mCur, lengthBytes);
} catch (ParseException e) {
- Rlog.e(LOG_TAG, e.getMessage());
ret = null;
+ //This is caught by createFromPdu(byte[] pdu)
+ throw new RuntimeException(e.getMessage());
}
mCur += lengthBytes;
diff --git a/src/java/com/android/internal/telephony/sip/SipCommandInterface.java b/src/java/com/android/internal/telephony/sip/SipCommandInterface.java
index 3fc4e85..49c9933 100644
--- a/src/java/com/android/internal/telephony/sip/SipCommandInterface.java
+++ b/src/java/com/android/internal/telephony/sip/SipCommandInterface.java
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2010 The Android Open Source Project
- * Copyright (c) 2012-13, The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/java/com/android/internal/telephony/test/SimulatedCommands.java b/src/java/com/android/internal/telephony/test/SimulatedCommands.java
index 28e4d64..d4d012e 100644
--- a/src/java/com/android/internal/telephony/test/SimulatedCommands.java
+++ b/src/java/com/android/internal/telephony/test/SimulatedCommands.java
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2006 The Android Open Source Project
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/java/com/android/internal/telephony/uicc/IccCardProxy.java b/src/java/com/android/internal/telephony/uicc/IccCardProxy.java
index 733af64..c512ecf 100644
--- a/src/java/com/android/internal/telephony/uicc/IccCardProxy.java
+++ b/src/java/com/android/internal/telephony/uicc/IccCardProxy.java
@@ -604,8 +604,9 @@
@Override
public boolean getIccLockEnabled() {
synchronized (mLock) {
- /* defaults to true, if ICC is absent */
- Boolean retValue = mUiccApplication != null ? mUiccApplication.getIccLockEnabled() : true;
+ /* defaults to false, if ICC is absent/deactivated */
+ Boolean retValue = mUiccApplication != null ?
+ mUiccApplication.getIccLockEnabled() : false;
return retValue;
}
}
@@ -613,11 +614,29 @@
@Override
public boolean getIccFdnEnabled() {
synchronized (mLock) {
- Boolean retValue = mUiccApplication != null ? mUiccApplication.getIccFdnEnabled() : false;
+ Boolean retValue = mUiccApplication != null ?
+ mUiccApplication.getIccFdnEnabled() : false;
return retValue;
}
}
+ public boolean getIccFdnAvailable() {
+ boolean retValue = mUiccApplication != null ? mUiccApplication.getIccFdnAvailable() : false;
+ return retValue;
+ }
+
+ public boolean getIccPin2Blocked() {
+ /* defaults to disabled */
+ Boolean retValue = mUiccApplication != null ? mUiccApplication.getIccPin2Blocked() : false;
+ return retValue;
+ }
+
+ public boolean getIccPuk2Blocked() {
+ /* defaults to disabled */
+ Boolean retValue = mUiccApplication != null ? mUiccApplication.getIccPuk2Blocked() : false;
+ return retValue;
+ }
+
@Override
public void setIccLockEnabled(boolean enabled, String password, Message onComplete) {
synchronized (mLock) {
diff --git a/src/java/com/android/internal/telephony/uicc/UiccCardApplication.java b/src/java/com/android/internal/telephony/uicc/UiccCardApplication.java
index 0715b0e..d125dbe 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccCardApplication.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccCardApplication.java
@@ -40,10 +40,14 @@
private static final String LOG_TAG = "UiccCardApplication";
private static final boolean DBG = true;
- private static final int EVENT_QUERY_FACILITY_FDN_DONE = 1;
- private static final int EVENT_CHANGE_FACILITY_FDN_DONE = 2;
- private static final int EVENT_QUERY_FACILITY_LOCK_DONE = 3;
- private static final int EVENT_CHANGE_FACILITY_LOCK_DONE = 4;
+ private static final int EVENT_PIN1_PUK1_DONE = 1;
+ private static final int EVENT_CHANGE_PIN1_DONE = 2;
+ private static final int EVENT_CHANGE_PIN2_DONE = 3;
+ private static final int EVENT_QUERY_FACILITY_FDN_DONE = 4;
+ private static final int EVENT_CHANGE_FACILITY_FDN_DONE = 5;
+ private static final int EVENT_QUERY_FACILITY_LOCK_DONE = 6;
+ private static final int EVENT_CHANGE_FACILITY_LOCK_DONE = 7;
+ private static final int EVENT_PIN2_PUK2_DONE = 8;
private final Object mLock = new Object();
private UiccCard mUiccCard; //parent
@@ -59,6 +63,7 @@
private boolean mDesiredFdnEnabled;
private boolean mIccLockEnabled;
private boolean mDesiredPinLocked;
+ private boolean mIccFdnAvailable = true; // Default is enabled.
private CommandsInterface mCi;
private Context mContext;
@@ -209,10 +214,18 @@
return;
}
- int[] ints = (int[])ar.result;
- if(ints.length != 0) {
- mIccFdnEnabled = (0!=ints[0]);
- if (DBG) log("Query facility lock : " + mIccFdnEnabled);
+ int[] result = (int[])ar.result;
+ if(result.length != 0) {
+ //0 - Available & Disabled, 1-Available & Enabled, 2-Unavailable.
+ if (result[0] == 2) {
+ mIccFdnEnabled = false;
+ mIccFdnAvailable = false;
+ } else {
+ mIccFdnEnabled = (result[0] == 1) ? true : false;
+ mIccFdnAvailable = true;
+ }
+ log("Query facility FDN : FDN service available: "+ mIccFdnAvailable
+ +" enabled: " + mIccFdnEnabled);
} else {
loge("Bogus facility lock response");
}
@@ -221,14 +234,18 @@
private void onChangeFdnDone(AsyncResult ar) {
synchronized (mLock) {
+ int attemptsRemaining = -1;
+
if (ar.exception == null) {
mIccFdnEnabled = mDesiredFdnEnabled;
if (DBG) log("EVENT_CHANGE_FACILITY_FDN_DONE: " +
"mIccFdnEnabled=" + mIccFdnEnabled);
} else {
+ attemptsRemaining = parsePinPukErrorResult(ar);
loge("Error change facility fdn with exception " + ar.exception);
}
Message response = (Message)ar.userObj;
+ response.arg1 = attemptsRemaining;
AsyncResult.forMessage(response).exception = ar.exception;
response.sendToTarget();
}
@@ -297,15 +314,38 @@
/** REMOVE when mIccLockEnabled is not needed */
private void onChangeFacilityLock(AsyncResult ar) {
synchronized (mLock) {
+ int attemptsRemaining = -1;
+
if (ar.exception == null) {
mIccLockEnabled = mDesiredPinLocked;
if (DBG) log( "EVENT_CHANGE_FACILITY_LOCK_DONE: mIccLockEnabled= "
+ mIccLockEnabled);
} else {
+ attemptsRemaining = parsePinPukErrorResult(ar);
loge("Error change facility lock with exception " + ar.exception);
}
- AsyncResult.forMessage(((Message)ar.userObj)).exception = ar.exception;
- ((Message)ar.userObj).sendToTarget();
+ Message response = (Message)ar.userObj;
+ AsyncResult.forMessage(response).exception = ar.exception;
+ response.arg1 = attemptsRemaining;
+ response.sendToTarget();
+ }
+ }
+
+ /**
+ * Parse the error response to obtain number of attempts remaining
+ */
+ private int parsePinPukErrorResult(AsyncResult ar) {
+ int[] result = (int[]) ar.result;
+ if (result == null) {
+ return -1;
+ } else {
+ int length = result.length;
+ int attemptsRemaining = -1;
+ if (length > 0) {
+ attemptsRemaining = result[0];
+ }
+ log("parsePinPukErrorResult: attemptsRemaining=" + attemptsRemaining);
+ return attemptsRemaining;
}
}
@@ -321,6 +361,22 @@
}
switch (msg.what) {
+ case EVENT_PIN1_PUK1_DONE:
+ case EVENT_PIN2_PUK2_DONE:
+ case EVENT_CHANGE_PIN1_DONE:
+ case EVENT_CHANGE_PIN2_DONE:
+ // a PIN/PUK/PIN2/PUK2 complete
+ // request has completed. ar.userObj is the response Message
+ int attemptsRemaining = -1;
+ ar = (AsyncResult)msg.obj;
+ if ((ar.exception != null) && (ar.result != null)) {
+ attemptsRemaining = parsePinPukErrorResult(ar);
+ }
+ Message response = (Message)ar.userObj;
+ AsyncResult.forMessage(response).exception = ar.exception;
+ response.arg1 = attemptsRemaining;
+ response.sendToTarget();
+ break;
case EVENT_QUERY_FACILITY_FDN_DONE:
ar = (AsyncResult)msg.obj;
onQueryFdnEnabled(ar);
@@ -520,6 +576,34 @@
* Handler.
*
* onComplete.obj will be an AsyncResult
+ * onComplete.arg1 = remaining attempts before puk locked or -1 if unknown
+ *
+ * ((AsyncResult)onComplete.obj).exception == null on success
+ * ((AsyncResult)onComplete.obj).exception != null on fail
+ *
+ * If the supplied PIN is incorrect:
+ * ((AsyncResult)onComplete.obj).exception != null
+ * && ((AsyncResult)onComplete.obj).exception
+ * instanceof com.android.internal.telephony.gsm.CommandException)
+ * && ((CommandException)(((AsyncResult)onComplete.obj).exception))
+ * .getCommandError() == CommandException.Error.PASSWORD_INCORRECT
+ */
+ public void supplyPin (String pin, Message onComplete) {
+ synchronized (mLock) {
+ mCi.supplyIccPinForApp(pin, mAid, mHandler.obtainMessage(EVENT_PIN1_PUK1_DONE,
+ onComplete));
+ }
+ }
+
+ /**
+ * Supply the ICC PUK to the ICC
+ *
+ * When the operation is complete, onComplete will be sent to its
+ * Handler.
+ *
+ * onComplete.obj will be an AsyncResult
+ * onComplete.arg1 = remaining attempts before Icc will be permanently unusable
+ * or -1 if unknown
*
* ((AsyncResult)onComplete.obj).exception == null on success
* ((AsyncResult)onComplete.obj).exception != null on fail
@@ -533,27 +617,24 @@
*
*
*/
- public void supplyPin (String pin, Message onComplete) {
- synchronized (mLock) {
- mCi.supplyIccPin(pin, onComplete);
- }
- }
-
public void supplyPuk (String puk, String newPin, Message onComplete) {
synchronized (mLock) {
- mCi.supplyIccPuk(puk, newPin, onComplete);
+ mCi.supplyIccPukForApp(puk, newPin, mAid,
+ mHandler.obtainMessage(EVENT_PIN1_PUK1_DONE, onComplete));
}
}
public void supplyPin2 (String pin2, Message onComplete) {
synchronized (mLock) {
- mCi.supplyIccPin2(pin2, onComplete);
+ mCi.supplyIccPin2ForApp(pin2, mAid,
+ mHandler.obtainMessage(EVENT_PIN2_PUK2_DONE, onComplete));
}
}
public void supplyPuk2 (String puk2, String newPin2, Message onComplete) {
synchronized (mLock) {
- mCi.supplyIccPuk2(puk2, newPin2, onComplete);
+ mCi.supplyIccPuk2ForApp(puk2, newPin2, mAid,
+ mHandler.obtainMessage(EVENT_PIN2_PUK2_DONE, onComplete));
}
}
@@ -597,6 +678,15 @@
}
/**
+ * Check whether fdn (fixed dialing number) service is available.
+ * @return true if ICC fdn service available
+ * false if ICC fdn service not available
+ */
+ public boolean getIccFdnAvailable() {
+ return mIccFdnAvailable;
+ }
+
+ /**
* Set the ICC pin lock enabled or disabled
* When the operation is complete, onComplete will be sent to its handler
*
@@ -659,6 +749,7 @@
* @param newPassword is the new password
* @param onComplete
* onComplete.obj will be an AsyncResult
+ * onComplete.arg1 = attempts remaining or -1 if unknown
* ((AsyncResult)onComplete.obj).exception == null on success
* ((AsyncResult)onComplete.obj).exception != null on fail
*/
@@ -667,7 +758,7 @@
synchronized (mLock) {
if (DBG) log("changeIccLockPassword");
mCi.changeIccPinForApp(oldPassword, newPassword, mAid,
- onComplete);
+ mHandler.obtainMessage(EVENT_CHANGE_PIN1_DONE, onComplete));
}
}
@@ -687,7 +778,25 @@
synchronized (mLock) {
if (DBG) log("changeIccFdnPassword");
mCi.changeIccPin2ForApp(oldPassword, newPassword, mAid,
- onComplete);
+ mHandler.obtainMessage(EVENT_CHANGE_PIN2_DONE, onComplete));
+ }
+ }
+
+ /**
+ * @return true if ICC card is PIN2 blocked
+ */
+ public boolean getIccPin2Blocked() {
+ synchronized (mLock) {
+ return mPin2State == PinState.PINSTATE_ENABLED_BLOCKED;
+ }
+ }
+
+ /**
+ * @return true if ICC card is PUK2 blocked
+ */
+ public boolean getIccPuk2Blocked() {
+ synchronized (mLock) {
+ return mPin2State == PinState.PINSTATE_ENABLED_PERM_BLOCKED;
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadCommands.java b/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadCommands.java
index 72d2d62..ec6e230 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadCommands.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadCommands.java
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2011 The Android Open Source Project
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.