Merge "frameworks/base/telephony: Release wakelock on RIL request send error"
diff --git a/core/java/com/android/internal/app/NetInitiatedActivity.java b/core/java/com/android/internal/app/NetInitiatedActivity.java
index 36f45b2..6039cc2 100755
--- a/core/java/com/android/internal/app/NetInitiatedActivity.java
+++ b/core/java/com/android/internal/app/NetInitiatedActivity.java
@@ -26,6 +26,8 @@
 import android.widget.Toast;
 import android.util.Log;
 import android.location.LocationManager;
+
+import com.android.internal.R;
 import com.android.internal.location.GpsNetInitiatedHandler;
 
 /**
@@ -42,10 +44,6 @@
     private static final int POSITIVE_BUTTON = AlertDialog.BUTTON_POSITIVE;
     private static final int NEGATIVE_BUTTON = AlertDialog.BUTTON_NEGATIVE;
 
-    // Dialog button text
-    public static final String BUTTON_TEXT_ACCEPT = "Accept";
-    public static final String BUTTON_TEXT_DENY = "Deny";
-
     // Received ID from intent, -1 when no notification is in progress
     private int notificationId = -1;
 
@@ -67,12 +65,13 @@
         // Set up the "dialog"
         final Intent intent = getIntent();
         final AlertController.AlertParams p = mAlertParams;
+        Context context = getApplicationContext();
         p.mIconId = com.android.internal.R.drawable.ic_dialog_usb;
         p.mTitle = intent.getStringExtra(GpsNetInitiatedHandler.NI_INTENT_KEY_TITLE);
         p.mMessage = intent.getStringExtra(GpsNetInitiatedHandler.NI_INTENT_KEY_MESSAGE);
-        p.mPositiveButtonText = BUTTON_TEXT_ACCEPT;
+        p.mPositiveButtonText = String.format(context.getString(R.string.gpsVerifYes));
         p.mPositiveButtonListener = this;
-        p.mNegativeButtonText = BUTTON_TEXT_DENY;
+        p.mNegativeButtonText = String.format(context.getString(R.string.gpsVerifNo));
         p.mNegativeButtonListener = this;
 
         notificationId = intent.getIntExtra(GpsNetInitiatedHandler.NI_INTENT_KEY_NOTIF_ID, -1);
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 1e007d36..c56b571 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2273,4 +2273,20 @@
     <!-- Shown when the users bandwidth is reduced because of excessive data use -->
     <string name="throttled_notification_title">Mobile data limit exceeded</string>
     <string name="throttled_notification_message">Touch to learn more about mobile data use</string>
+
+    <!-- Network positioning notification ticker. The name of the user (e.g. John Doe) who sent
+         the request is shown as a dynamic string. -->
+    <string name="gpsNotifTicker">Location request from <xliff:g id="name">%s</xliff:g></string>
+    <!-- Network positioning notification and verification title to inform the user about
+         an incoming location request. -->
+    <string name="gpsNotifTitle">Location request</string>
+    <!-- Network positioning notification message. The name of the user (e.g. John Doe) and
+         service (SUPL-service) who sent the request is shown as dynamic strings.
+         Translation should not be longer than master text. -->
+    <string name="gpsNotifMessage">Requested by <xliff:g id="name">%1$s</xliff:g> (<xliff:g id="service" example="SUPL-service">%2$s</xliff:g>)</string>
+    <!-- Network positioning verification Yes. Button to push to share location information. -->
+    <string name="gpsVerifYes">Yes</string>
+    <!-- Network positioning verification No. Button to push to deny sharing of location
+         information. -->
+    <string name="gpsVerifNo">No</string>
 </resources>
diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
index a5466d1..fc98e06 100755
--- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
+++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
@@ -27,6 +27,8 @@
 import android.os.RemoteException;
 import android.util.Log;
 
+import com.android.internal.R;
+
 /**
  * A GPS Network-initiated Handler class used by LocationManager.
  *
@@ -187,8 +189,8 @@
             return;
         }
       
-    	String title = getNotifTitle(notif);
-    	String message = getNotifMessage(notif);
+    	String title = getNotifTitle(notif, mContext);
+    	String message = getNotifMessage(notif, mContext);
         
         if (DEBUG) Log.d(TAG, "setNiNotification, notifyId: " + notif.notificationId +
         		", title: " + title +
@@ -208,7 +210,7 @@
         }        
         
         mNiNotification.flags = Notification.FLAG_ONGOING_EVENT;
-        mNiNotification.tickerText = getNotifTicker(notif);
+        mNiNotification.tickerText = getNotifTicker(notif, mContext);
         
         // if not to popup dialog immediately, pending intent will open the dialog
         Intent intent = !mPopupImmediately ? getDlgIntent(notif) : new Intent();    	        
@@ -239,8 +241,8 @@
     private Intent getDlgIntent(GpsNiNotification notif)
     {
     	Intent intent = new Intent();
-    	String title = getDialogTitle(notif);
-    	String message = getDialogMessage(notif);
+    	String title = getDialogTitle(notif, mContext);
+    	String message = getDialogMessage(notif, mContext);
     	
     	// directly bring up the NI activity
     	intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
@@ -417,41 +419,40 @@
     }
     
     // change this to configure notification display
-    static private String getNotifTicker(GpsNiNotification notif)
+    static private String getNotifTicker(GpsNiNotification notif, Context context)
     {
-    	String ticker = String.format("Position request! ReqId: [%s] ClientName: [%s]",
+    	String ticker = String.format(context.getString(R.string.gpsNotifTicker),
     			decodeString(notif.requestorId, mIsHexInput, notif.requestorIdEncoding),
     			decodeString(notif.text, mIsHexInput, notif.textEncoding));
     	return ticker;
     }
     
     // change this to configure notification display
-    static private String getNotifTitle(GpsNiNotification notif)
+    static private String getNotifTitle(GpsNiNotification notif, Context context)
     {
-    	String title = String.format("Position Request");
+    	String title = String.format(context.getString(R.string.gpsNotifTitle));
     	return title;
     }
     
     // change this to configure notification display
-    static private String getNotifMessage(GpsNiNotification notif)
+    static private String getNotifMessage(GpsNiNotification notif, Context context)
     {
-    	String message = String.format(
-    			"NI Request received from [%s] for client [%s]!", 
+    	String message = String.format(context.getString(R.string.gpsNotifMessage),
     			decodeString(notif.requestorId, mIsHexInput, notif.requestorIdEncoding),
     			decodeString(notif.text, mIsHexInput, notif.textEncoding));
     	return message;
     }       
     
     // change this to configure dialog display (for verification)
-    static public String getDialogTitle(GpsNiNotification notif)
+    static public String getDialogTitle(GpsNiNotification notif, Context context)
     {
-    	return getNotifTitle(notif);
+    	return getNotifTitle(notif, context);
     }
     
     // change this to configure dialog display (for verification)
-    static private String getDialogMessage(GpsNiNotification notif)
+    static private String getDialogMessage(GpsNiNotification notif, Context context)
     {
-    	return getNotifMessage(notif);
+    	return getNotifMessage(notif, context);
     }
     
 }
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
index f869dbd..30c8d95 100644
--- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -32,6 +32,7 @@
 import com.android.internal.telephony.cdma.sms.CdmaSmsSubaddress;
 import com.android.internal.telephony.cdma.sms.SmsEnvelope;
 import com.android.internal.telephony.cdma.sms.UserData;
+import com.android.internal.util.BitwiseInputStream;
 import com.android.internal.util.HexDump;
 
 import java.io.BufferedInputStream;
@@ -72,6 +73,16 @@
     static final String LOG_TAG = "CDMA";
     static private final String LOGGABLE_TAG = "CDMA:SMS";
 
+    private final static byte TELESERVICE_IDENTIFIER                    = 0x00;
+    private final static byte SERVICE_CATEGORY                          = 0x01;
+    private final static byte ORIGINATING_ADDRESS                       = 0x02;
+    private final static byte ORIGINATING_SUB_ADDRESS                   = 0x03;
+    private final static byte DESTINATION_ADDRESS                       = 0x04;
+    private final static byte DESTINATION_SUB_ADDRESS                   = 0x05;
+    private final static byte BEARER_REPLY_OPTION                       = 0x06;
+    private final static byte CAUSE_CODES                               = 0x07;
+    private final static byte BEARER_DATA                               = 0x08;
+
     /**
      *  Status of a previously submitted SMS.
      *  This field applies to SMS Delivery Acknowledge messages. 0 indicates success;
@@ -267,6 +278,7 @@
             System.arraycopy(data, 2, pdu, 0, size);
             // the message has to be parsed before it can be displayed
             // see gsm.SmsMessage
+            msg.parsePduFromEfRecord(pdu);
             return msg;
         } catch (RuntimeException ex) {
             Log.e(LOG_TAG, "SMS PDU parsing failed: ", ex);
@@ -539,6 +551,143 @@
     }
 
     /**
+     * Decodes 3GPP2 sms stored in CSIM/RUIM cards As per 3GPP2 C.S0015-0
+     */
+    private void parsePduFromEfRecord(byte[] pdu) {
+        ByteArrayInputStream bais = new ByteArrayInputStream(pdu);
+        DataInputStream dis = new DataInputStream(bais);
+        SmsEnvelope env = new SmsEnvelope();
+        CdmaSmsAddress addr = new CdmaSmsAddress();
+        CdmaSmsSubaddress subAddr = new CdmaSmsSubaddress();
+
+        try {
+            env.messageType = dis.readByte();
+
+            while (dis.available() > 0) {
+                int parameterId = dis.readByte();
+                int parameterLen = dis.readByte();
+                byte[] parameterData = new byte[parameterLen];
+
+                switch (parameterId) {
+                    case TELESERVICE_IDENTIFIER:
+                        /*
+                         * 16 bit parameter that identifies which upper layer
+                         * service access point is sending or should receive
+                         * this message
+                         */
+                        env.teleService = dis.readUnsignedShort();
+                        Log.i(LOG_TAG, "teleservice = " + env.teleService);
+                        break;
+                    case SERVICE_CATEGORY:
+                        /*
+                         * 16 bit parameter that identifies type of service as
+                         * in 3GPP2 C.S0015-0 Table 3.4.3.2-1
+                         */
+                        env.serviceCategory = dis.readUnsignedShort();
+                        break;
+                    case ORIGINATING_ADDRESS:
+                    case DESTINATION_ADDRESS:
+                        dis.read(parameterData, 0, parameterLen);
+                        BitwiseInputStream addrBis = new BitwiseInputStream(parameterData);
+                        addr.digitMode = addrBis.read(1);
+                        addr.numberMode = addrBis.read(1);
+                        int numberType = 0;
+                        if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) {
+                            numberType = addrBis.read(3);
+                            addr.ton = numberType;
+
+                            if (addr.numberMode == CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK)
+                                addr.numberPlan = addrBis.read(4);
+                        }
+
+                        addr.numberOfDigits = addrBis.read(8);
+
+                        byte[] data = new byte[addr.numberOfDigits];
+                        byte b = 0x00;
+
+                        if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF) {
+                            /* As per 3GPP2 C.S0005-0 Table 2.7.1.3.2.4-4 */
+                            for (int index = 0; index < addr.numberOfDigits; index++) {
+                                b = (byte) (0xF & addrBis.read(4));
+                                // convert the value if it is 4-bit DTMF to 8
+                                // bit
+                                data[index] = convertDtmfToAscii(b);
+                            }
+                        } else if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) {
+                            if (addr.numberMode == CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK) {
+                                for (int index = 0; index < addr.numberOfDigits; index++) {
+                                    b = (byte) (0xFF & addrBis.read(8));
+                                    data[index] = b;
+                                }
+
+                            } else if (addr.numberMode == CdmaSmsAddress.NUMBER_MODE_DATA_NETWORK) {
+                                if (numberType == 2)
+                                    Log.e(LOG_TAG, "TODO: Originating Addr is email id");
+                                else
+                                    Log.e(LOG_TAG,
+                                          "TODO: Originating Addr is data network address");
+                            } else {
+                                Log.e(LOG_TAG, "Originating Addr is of incorrect type");
+                            }
+                        } else {
+                            Log.e(LOG_TAG, "Incorrect Digit mode");
+                        }
+                        addr.origBytes = data;
+                        Log.i(LOG_TAG, "Originating Addr=" + addr.toString());
+                        break;
+                    case ORIGINATING_SUB_ADDRESS:
+                    case DESTINATION_SUB_ADDRESS:
+                        dis.read(parameterData, 0, parameterLen);
+                        BitwiseInputStream subAddrBis = new BitwiseInputStream(parameterData);
+                        subAddr.type = subAddrBis.read(3);
+                        subAddr.odd = subAddrBis.readByteArray(1)[0];
+                        int subAddrLen = subAddrBis.read(8);
+                        byte[] subdata = new byte[subAddrLen];
+                        for (int index = 0; index < subAddrLen; index++) {
+                            b = (byte) (0xFF & subAddrBis.read(4));
+                            // convert the value if it is 4-bit DTMF to 8 bit
+                            subdata[index] = convertDtmfToAscii(b);
+                        }
+                        subAddr.origBytes = subdata;
+                        break;
+                    case BEARER_REPLY_OPTION:
+                        dis.read(parameterData, 0, parameterLen);
+                        BitwiseInputStream replyOptBis = new BitwiseInputStream(parameterData);
+                        env.bearerReply = replyOptBis.read(6);
+                        break;
+                    case CAUSE_CODES:
+                        dis.read(parameterData, 0, parameterLen);
+                        BitwiseInputStream ccBis = new BitwiseInputStream(parameterData);
+                        env.replySeqNo = ccBis.readByteArray(6)[0];
+                        env.errorClass = ccBis.readByteArray(2)[0];
+                        if (env.errorClass != 0x00)
+                            env.causeCode = ccBis.readByteArray(8)[0];
+                        break;
+                    case BEARER_DATA:
+                        dis.read(parameterData, 0, parameterLen);
+                        env.bearerData = parameterData;
+                        break;
+                    default:
+                        throw new Exception("unsupported parameterId (" + parameterId + ")");
+                }
+            }
+            bais.close();
+            dis.close();
+        } catch (Exception ex) {
+            Log.e(LOG_TAG, "parsePduFromEfRecord: conversion from pdu to SmsMessage failed" + ex);
+        }
+
+        // link the filled objects to this SMS
+        originatingAddress = addr;
+        env.origAddress = addr;
+        env.origSubaddress = subAddr;
+        mEnvelope = env;
+        mPdu = pdu;
+
+        parseSms();
+    }
+
+    /**
      * Parses a SMS message from its BearerData stream. (mobile-terminated only)
      */
     protected void parseSms() {