Merge "docs: Added docs for lint tool. Change-Id: I06192262b56e0333bcfbcac223395788f7b0d072 Bug: 5942358" into jb-dev
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 4b93e74..833064e 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -163,6 +163,12 @@
     <assign-permission name="android.permission.FORCE_STOP_PACKAGES" uid="shell" />
     <assign-permission name="android.permission.STOP_APP_SWITCHES" uid="shell" />
     <assign-permission name="android.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY" uid="shell" />
+    <assign-permission name="android.permission.GRANT_REVOKE_PERMISSIONS" uid="shell" />
+    <assign-permission name="android.permission.SET_KEYBOARD_LAYOUT" uid="shell" />
+    <assign-permission name="android.permission.GET_DETAILED_TASKS" uid="shell" />
+    <assign-permission name="android.permission.SET_SCREEN_COMPATIBILITY" uid="shell" />
+    <assign-permission name="android.permission.READ_EXTERNAL_STORAGE" uid="shell" />
+    <assign-permission name="android.permission.WRITE_EXTERNAL_STORAGE" uid="shell" />
 
     <assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="media" />
     <assign-permission name="android.permission.ACCESS_DRM" uid="media" />
diff --git a/docs/html/sdk/installing/installing-adt.jd b/docs/html/sdk/installing/installing-adt.jd
index 60f67a2..414b97b 100644
--- a/docs/html/sdk/installing/installing-adt.jd
+++ b/docs/html/sdk/installing/installing-adt.jd
@@ -1,9 +1,9 @@
 page.title=Installing the Eclipse Plugin
 walkthru=1
-adt.zip.version=20.0.1
-adt.zip.download=ADT-20.0.1.zip
-adt.zip.bytes=12387574
-adt.zip.checksum=6ebd7f8566bfd2cd031b07d56d49542d
+adt.zip.version=20.0.2
+adt.zip.download=ADT-20.0.2.zip
+adt.zip.bytes=12388464
+adt.zip.checksum=8e727bcdc9789c900784a82e6330ec22
 
 @jd:body
 
diff --git a/docs/html/tools/help/bmgr.jd b/docs/html/tools/help/bmgr.jd
index 2248fa6..8823f33 100644
--- a/docs/html/tools/help/bmgr.jd
+++ b/docs/html/tools/help/bmgr.jd
@@ -7,9 +7,6 @@
 
 <div id="qv-wrapper">
 <div id="qv">
-  <h2>bmgr quickview</h2>
-<p><code>bmgr</code> lets you control the backup/restore system on an Android device.
-
   <h2>In this document</h2>
   <ol>
 <li><a href="#backup">Forcing a Backup Operation</a></li>
diff --git a/docs/html/tools/help/monitor.jd b/docs/html/tools/help/monitor.jd
index 8e2ea36..18fb49a 100644
--- a/docs/html/tools/help/monitor.jd
+++ b/docs/html/tools/help/monitor.jd
@@ -1,7 +1,7 @@
-page.title=Debug Monitor
+page.title=Device Monitor
 @jd:body
 
-<p>Android Debug Monitor is a stand-alone tool that provides a graphical user interface for
+<p>Android Device Monitor is a stand-alone tool that provides a graphical user interface for
 several Android application debugging and analysis tools. The Monitor tool does not
 require installation of a integrated development environment, such as Eclipse, and encapsulates the
 following tools:</p>
@@ -16,9 +16,9 @@
 
 <h2 id="usage">Usage</h2>
 
-<p>To start Debug Monitor, enter the following command from the SDK <code>tools/</code>
+<p>To start Device Monitor, enter the following command from the SDK <code>tools/</code>
 directory:</p>
   <pre>monitor</pre>
 
-<p>Start an Android emulator or connect an Android device via USB cable, and connect the Debug
+<p>Start an Android emulator or connect an Android device via USB cable, and connect Device
 Monitor to the device by selecting it in the <strong>Devices</strong> window.</p>
diff --git a/docs/html/tools/sdk/eclipse-adt.jd b/docs/html/tools/sdk/eclipse-adt.jd
index 947e463..bdb4a9e 100644
--- a/docs/html/tools/sdk/eclipse-adt.jd
+++ b/docs/html/tools/sdk/eclipse-adt.jd
@@ -96,8 +96,41 @@
 <div class="toggleable opened">
   <a href="#" onclick="return toggleDiv(this)">
   <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px"
-    width="9px" />
-ADT 20.0.1</a> <em>(June 2012)</em>
+    width="9px"/>
+ADT 20.0.2</a> <em>(July 2012)</em>
+  <div class="toggleme">
+<dl>
+  <dt>Dependencies:</dt>
+
+  <dd>
+    <ul>
+      <li>Java 1.6 or higher is required for ADT 20.0.2.</li>
+      <li>Eclipse Helios (Version 3.6.2) or higher is required for ADT 20.0.2.</li>
+      <li>ADT 20.0.2 is designed for use with <a href="{@docRoot}tools/sdk/tools-notes.html">SDK
+      Tools r20.0.1</a>. If you haven't already installed SDK Tools r20.0.1 into your SDK, use the
+      Android SDK Manager to do so.</li>
+    </ul>
+  </dd>
+
+  <dt>Bug fixes:</dt>
+  <dd>
+    <ul>
+      <li>Fixed keybindings in various XML editors for Eclipse 4.x.</li>
+      <li>Fixed bug when creating layout configurations that already exist.</li>
+    </ul>
+  </dd>
+
+</dl>
+
+</div>
+</div>
+
+
+<div class="toggleable closed">
+  <a href="#" onclick="return toggleDiv(this)">
+  <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-img" height="9px"
+    width="9px"/>
+ADT 20.0.1</a> <em>(July 2012)</em>
   <div class="toggleme">
 <dl>
   <dt>Dependencies:</dt>
diff --git a/docs/html/training/basics/firstapp/creating-project.jd b/docs/html/training/basics/firstapp/creating-project.jd
index 97f2a5d..2ea8b2f 100644
--- a/docs/html/training/basics/firstapp/creating-project.jd
+++ b/docs/html/training/basics/firstapp/creating-project.jd
@@ -41,10 +41,10 @@
 SDK tools from a command line.</p>
 
 <p class="note"><strong>Note:</strong> You should already have the Android SDK installed, and if
-you're using Eclipse, you should also have the <a
-href="{@docRoot}tools/sdk/eclipse-adt.html">ADT plugin</a> installed. If you don't have
-these, follow the guide to <a href="{@docRoot}sdk/installing/index.html">Installing the Android SDK</a>
-before you start this lesson.</p>
+you're using Eclipse, you should also have the <a href="{@docRoot}tools/sdk/eclipse-adt.html">ADT
+plugin</a> installed (version 20.0.0 or higher). If you don't have these, follow the guide to <a
+href="{@docRoot}sdk/installing/index.html">Installing the Android SDK</a> before you start this
+lesson.</p>
 
 
 <h2 id="Eclipse">Create a Project with Eclipse</h2>
diff --git a/docs/html/training/basics/firstapp/index.jd b/docs/html/training/basics/firstapp/index.jd
index e2b9cff..4c1a0dc3 100644
--- a/docs/html/training/basics/firstapp/index.jd
+++ b/docs/html/training/basics/firstapp/index.jd
@@ -14,8 +14,9 @@
 <h2>Dependencies and prerequisites</h2> 
 
 <ul>
-  <li>Android 1.6 or higher</li>
   <li><a href="http://developer.android.com/sdk/index.html">Android SDK</a></li>
+  <li><a href="{@docRoot}tools/sdk/eclipse-adt.html">ADT Plugin</a> 20.0.0 or higher
+    (if you're using Eclipse)</li>
 </ul>
  
 </div> 
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
index 504bb63..fb6ff24 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
@@ -147,7 +147,7 @@
 
         if (enableScreenRotation) {
             if (DEBUG) Log.d(TAG, "Rotation sensor for lock screen On!");
-            mWindowLayoutParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR;
+            mWindowLayoutParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;
         } else {
             if (DEBUG) Log.d(TAG, "Rotation sensor for lock screen Off!");
             mWindowLayoutParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
diff --git a/telephony/java/android/telephony/cdma/CdmaSmsCbProgramData.java b/telephony/java/android/telephony/cdma/CdmaSmsCbProgramData.java
index f94efd8..010ad2b 100644
--- a/telephony/java/android/telephony/cdma/CdmaSmsCbProgramData.java
+++ b/telephony/java/android/telephony/cdma/CdmaSmsCbProgramData.java
@@ -81,8 +81,8 @@
     /** Service category to modify. */
     private final int mCategory;
 
-    /** Language used for service category name (ISO 639 two character code). */
-    private final String mLanguage;
+    /** Language used for service category name (defined in BearerData.LANGUAGE_*). */
+    private final int mLanguage;
 
     /** Maximum number of messages to store for this service category. */
     private final int mMaxMessages;
@@ -94,7 +94,7 @@
     private final String mCategoryName;
 
     /** Create a new CdmaSmsCbProgramData object with the specified values. */
-    public CdmaSmsCbProgramData(int operation, int category, String language, int maxMessages,
+    public CdmaSmsCbProgramData(int operation, int category, int language, int maxMessages,
             int alertOption, String categoryName) {
         mOperation = operation;
         mCategory = category;
@@ -108,7 +108,7 @@
     CdmaSmsCbProgramData(Parcel in) {
         mOperation = in.readInt();
         mCategory = in.readInt();
-        mLanguage = in.readString();
+        mLanguage = in.readInt();
         mMaxMessages = in.readInt();
         mAlertOption = in.readInt();
         mCategoryName = in.readString();
@@ -124,7 +124,7 @@
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(mOperation);
         dest.writeInt(mCategory);
-        dest.writeString(mLanguage);
+        dest.writeInt(mLanguage);
         dest.writeInt(mMaxMessages);
         dest.writeInt(mAlertOption);
         dest.writeString(mCategoryName);
@@ -147,10 +147,10 @@
     }
 
     /**
-     * Returns the ISO-639-1 language code for the service category name, or null if not present.
-     * @return a two-digit ISO-639-1 language code, e.g. "en" for English
+     * Returns the CDMA language code for this service category.
+     * @return one of the language values defined in BearerData.LANGUAGE_*
      */
-    public String getLanguageCode() {
+    public int getLanguage() {
         return mLanguage;
     }
 
@@ -171,7 +171,7 @@
     }
 
     /**
-     * Returns the service category name, in the language specified by {@link #getLanguageCode()}.
+     * Returns the service category name, in the language specified by {@link #getLanguage()}.
      * @return an optional service category name
      */
     public String getCategoryName() {
diff --git a/telephony/java/android/telephony/cdma/CdmaSmsCbProgramResults.java b/telephony/java/android/telephony/cdma/CdmaSmsCbProgramResults.java
new file mode 100644
index 0000000..68bfa3c
--- /dev/null
+++ b/telephony/java/android/telephony/cdma/CdmaSmsCbProgramResults.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.cdma;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * CDMA Service Category Program Results from SCPT teleservice SMS.
+ *
+ * {@hide}
+ */
+public class CdmaSmsCbProgramResults implements Parcelable {
+
+    /** Program result: success. */
+    public static final int RESULT_SUCCESS                  = 0;
+
+    /** Program result: memory limit exceeded. */
+    public static final int RESULT_MEMORY_LIMIT_EXCEEDED    = 1;
+
+    /** Program result: limit exceeded. */
+    public static final int RESULT_CATEGORY_LIMIT_EXCEEDED  = 2;
+
+    /** Program result: category already opted in. */
+    public static final int RESULT_CATEGORY_ALREADY_ADDED   = 3;
+
+    /** Program result: category already opted in. */
+    public static final int RESULT_CATEGORY_ALREADY_DELETED = 4;
+
+    /** Program result: invalid MAX_MESSAGES. */
+    public static final int RESULT_INVALID_MAX_MESSAGES     = 5;
+
+    /** Program result: invalid ALERT_OPTION. */
+    public static final int RESULT_INVALID_ALERT_OPTION     = 6;
+
+    /** Program result: invalid service category name. */
+    public static final int RESULT_INVALID_CATEGORY_NAME    = 7;
+
+    /** Program result: unspecified programming failure. */
+    public static final int RESULT_UNSPECIFIED_FAILURE      = 8;
+
+    /** Service category to modify. */
+    private final int mCategory;
+
+    /** Language used for service category name (defined in BearerData.LANGUAGE_*). */
+    private final int mLanguage;
+
+    /** Result of service category programming for this category. */
+    private final int mCategoryResult;
+
+    /** Create a new CdmaSmsCbProgramResults object with the specified values. */
+    public CdmaSmsCbProgramResults(int category, int language, int categoryResult) {
+        mCategory = category;
+        mLanguage = language;
+        mCategoryResult = categoryResult;
+    }
+
+    /** Create a new CdmaSmsCbProgramResults object from a Parcel. */
+    CdmaSmsCbProgramResults(Parcel in) {
+        mCategory = in.readInt();
+        mLanguage = in.readInt();
+        mCategoryResult = in.readInt();
+    }
+
+    /**
+     * Flatten this object into a Parcel.
+     *
+     * @param dest  The Parcel in which the object should be written.
+     * @param flags Additional flags about how the object should be written (ignored).
+     */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mCategory);
+        dest.writeInt(mLanguage);
+        dest.writeInt(mCategoryResult);
+    }
+
+    /**
+     * Returns the CDMA service category to modify.
+     * @return a 16-bit CDMA service category value
+     */
+    public int getCategory() {
+        return mCategory;
+    }
+
+    /**
+     * Returns the CDMA language code for this service category.
+     * @return one of the language values defined in BearerData.LANGUAGE_*
+     */
+    public int getLanguage() {
+        return mLanguage;
+    }
+
+    /**
+     * Returns the result of service programming for this category
+     * @return the result of service programming for this category
+     */
+    public int getCategoryResult() {
+        return mCategoryResult;
+    }
+
+    @Override
+    public String toString() {
+        return "CdmaSmsCbProgramResults{category=" + mCategory
+                + ", language=" + mLanguage + ", result=" + mCategoryResult + '}';
+    }
+
+    /**
+     * Describe the kinds of special objects contained in the marshalled representation.
+     * @return a bitmask indicating this Parcelable contains no special objects
+     */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Creator for unparcelling objects. */
+    public static final Parcelable.Creator<CdmaSmsCbProgramResults>
+            CREATOR = new Parcelable.Creator<CdmaSmsCbProgramResults>() {
+        @Override
+        public CdmaSmsCbProgramResults createFromParcel(Parcel in) {
+            return new CdmaSmsCbProgramResults(in);
+        }
+
+        @Override
+        public CdmaSmsCbProgramResults[] newArray(int size) {
+            return new CdmaSmsCbProgramResults[size];
+        }
+    };
+}
diff --git a/telephony/java/com/android/internal/telephony/SMSDispatcher.java b/telephony/java/com/android/internal/telephony/SMSDispatcher.java
index 07d733e..40c22a7 100644
--- a/telephony/java/com/android/internal/telephony/SMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/SMSDispatcher.java
@@ -339,6 +339,22 @@
     }
 
     /**
+     * Grabs a wake lock and sends intent as an ordered broadcast.
+     * Used for setting a custom result receiver for CDMA SCPD.
+     *
+     * @param intent intent to broadcast
+     * @param permission Receivers are required to have this permission
+     * @param resultReceiver the result receiver to use
+     */
+    public void dispatch(Intent intent, String permission, BroadcastReceiver resultReceiver) {
+        // Hold a wake lock for WAKE_LOCK_TIMEOUT seconds, enough to give any
+        // receivers time to take their own wake locks.
+        mWakeLock.acquire(WAKE_LOCK_TIMEOUT);
+        mContext.sendOrderedBroadcast(intent, permission, resultReceiver,
+                this, Activity.RESULT_OK, null, null);
+    }
+
+    /**
      * Called when SMS send completes. Broadcasts a sentIntent on success.
      * On failure, either sets up retries or broadcasts a sentIntent with
      * the failure in the result code.
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
index e6b45f6..a6b32f9 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
@@ -20,20 +20,23 @@
 import android.app.Activity;
 import android.app.PendingIntent;
 import android.app.PendingIntent.CanceledException;
-import android.content.ContentValues;
+import android.content.BroadcastReceiver;
+import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
-import android.database.Cursor;
-import android.database.SQLException;
+import android.content.res.Resources;
+import android.os.Bundle;
 import android.os.Message;
 import android.os.SystemProperties;
 import android.preference.PreferenceManager;
 import android.provider.Telephony;
 import android.provider.Telephony.Sms.Intents;
+import android.telephony.PhoneNumberUtils;
 import android.telephony.SmsCbMessage;
 import android.telephony.SmsManager;
 import android.telephony.SmsMessage.MessageClass;
 import android.telephony.cdma.CdmaSmsCbProgramData;
+import android.telephony.cdma.CdmaSmsCbProgramResults;
 import android.util.Log;
 
 import com.android.internal.telephony.CommandsInterface;
@@ -45,16 +48,17 @@
 import com.android.internal.telephony.SmsUsageMonitor;
 import com.android.internal.telephony.TelephonyProperties;
 import com.android.internal.telephony.WspTypeDecoder;
+import com.android.internal.telephony.cdma.sms.BearerData;
+import com.android.internal.telephony.cdma.sms.CdmaSmsAddress;
 import com.android.internal.telephony.cdma.sms.SmsEnvelope;
 import com.android.internal.telephony.cdma.sms.UserData;
-import com.android.internal.util.HexDump;
 
 import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
-import java.util.List;
-
-import android.content.res.Resources;
 
 
 final class CdmaSMSDispatcher extends SMSDispatcher {
@@ -107,15 +111,16 @@
      * {@link android.telephony.cdma.CdmaSmsCbProgramData} objects.
      */
     private void handleServiceCategoryProgramData(SmsMessage sms) {
-        List<CdmaSmsCbProgramData> programDataList = sms.getSmsCbProgramData();
+        ArrayList<CdmaSmsCbProgramData> programDataList = sms.getSmsCbProgramData();
         if (programDataList == null) {
             Log.e(TAG, "handleServiceCategoryProgramData: program data list is null!");
             return;
         }
 
         Intent intent = new Intent(Intents.SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED_ACTION);
-        intent.putExtra("program_data_list", (CdmaSmsCbProgramData[]) programDataList.toArray());
-        dispatch(intent, RECEIVE_SMS_PERMISSION);
+        intent.putExtra("sender", sms.getOriginatingAddress());
+        intent.putParcelableArrayListExtra("program_data", programDataList);
+        dispatch(intent, RECEIVE_SMS_PERMISSION, mScpResultsReceiver);
     }
 
     /** {@inheritDoc} */
@@ -425,4 +430,72 @@
         }
         return false;
     }
+
+    // Receiver for Service Category Program Data results.
+    // We already ACK'd the original SCPD SMS, so this sends a new response SMS.
+    // TODO: handle retries if the RIL returns an error.
+    private final BroadcastReceiver mScpResultsReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            int rc = getResultCode();
+            boolean success = (rc == Activity.RESULT_OK) || (rc == Intents.RESULT_SMS_HANDLED);
+            if (!success) {
+                Log.e(TAG, "SCP results error: result code = " + rc);
+                return;
+            }
+            Bundle extras = getResultExtras(false);
+            if (extras == null) {
+                Log.e(TAG, "SCP results error: missing extras");
+                return;
+            }
+            String sender = extras.getString("sender");
+            if (sender == null) {
+                Log.e(TAG, "SCP results error: missing sender extra.");
+                return;
+            }
+            ArrayList<CdmaSmsCbProgramResults> results
+                    = extras.getParcelableArrayList("results");
+            if (results == null) {
+                Log.e(TAG, "SCP results error: missing results extra.");
+                return;
+            }
+
+            BearerData bData = new BearerData();
+            bData.messageType = BearerData.MESSAGE_TYPE_SUBMIT;
+            bData.messageId = SmsMessage.getNextMessageId();
+            bData.serviceCategoryProgramResults = results;
+            byte[] encodedBearerData = BearerData.encode(bData);
+
+            ByteArrayOutputStream baos = new ByteArrayOutputStream(100);
+            DataOutputStream dos = new DataOutputStream(baos);
+            try {
+                dos.writeInt(SmsEnvelope.TELESERVICE_SCPT);
+                dos.writeInt(0); //servicePresent
+                dos.writeInt(0); //serviceCategory
+                CdmaSmsAddress destAddr = CdmaSmsAddress.parse(
+                        PhoneNumberUtils.cdmaCheckAndProcessPlusCode(sender));
+                dos.write(destAddr.digitMode);
+                dos.write(destAddr.numberMode);
+                dos.write(destAddr.ton); // number_type
+                dos.write(destAddr.numberPlan);
+                dos.write(destAddr.numberOfDigits);
+                dos.write(destAddr.origBytes, 0, destAddr.origBytes.length); // digits
+                // Subaddress is not supported.
+                dos.write(0); //subaddressType
+                dos.write(0); //subaddr_odd
+                dos.write(0); //subaddr_nbr_of_digits
+                dos.write(encodedBearerData.length);
+                dos.write(encodedBearerData, 0, encodedBearerData.length);
+                // Ignore the RIL response. TODO: implement retry if SMS send fails.
+                mCm.sendCdmaSms(baos.toByteArray(), null);
+            } catch (IOException e) {
+                Log.e(TAG, "exception creating SCP results PDU", e);
+            } finally {
+                try {
+                    dos.close();
+                } catch (IOException ignored) {
+                }
+            }
+        }
+    };
 }
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
index 7292b86..9a0ebed 100644
--- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -42,6 +42,7 @@
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.List;
 
 import static android.telephony.SmsMessage.MessageClass;
@@ -781,7 +782,7 @@
      * binder-call, and hence should be thread-safe, it has been
      * synchronized.
      */
-    private synchronized static int getNextMessageId() {
+    synchronized static int getNextMessageId() {
         // Testing and dialog with partners has indicated that
         // msgId==0 is (sometimes?) treated specially by lower levels.
         // Specifically, the ID is not preserved for delivery ACKs.
@@ -997,7 +998,7 @@
      * Returns the list of service category program data, if present.
      * @return a list of CdmaSmsCbProgramData objects, or null if not present
      */
-    List<CdmaSmsCbProgramData> getSmsCbProgramData() {
+    ArrayList<CdmaSmsCbProgramData> getSmsCbProgramData() {
         return mBearerData.serviceCategoryProgramData;
     }
 }
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
index 0f49762..5cacd23 100755
--- a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
@@ -18,9 +18,9 @@
 
 import android.content.res.Resources;
 import android.telephony.SmsCbCmasInfo;
-import android.telephony.SmsCbMessage;
 import android.telephony.SmsMessage;
 import android.telephony.cdma.CdmaSmsCbProgramData;
+import android.telephony.cdma.CdmaSmsCbProgramResults;
 import android.text.format.Time;
 import android.util.Log;
 
@@ -32,8 +32,6 @@
 import com.android.internal.util.BitwiseOutputStream;
 
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
 import java.util.TimeZone;
 
 import static android.telephony.SmsMessage.ENCODING_16BIT;
@@ -353,7 +351,14 @@
      * {@link android.telephony.cdma.CdmaSmsCbProgramData} objects containing the
      * operation(s) to perform.
      */
-    public List<CdmaSmsCbProgramData> serviceCategoryProgramData;
+    public ArrayList<CdmaSmsCbProgramData> serviceCategoryProgramData;
+
+    /**
+     * The Service Category Program Results subparameter informs the message center
+     * of the results of a Service Category Program Data request.
+     */
+    public ArrayList<CdmaSmsCbProgramResults> serviceCategoryProgramResults;
+
 
     private static class CodingException extends Exception {
         public CodingException(String s) {
@@ -857,6 +862,21 @@
         outStream.skip(6);
     }
 
+    private static void encodeScpResults(BearerData bData, BitwiseOutputStream outStream)
+        throws BitwiseOutputStream.AccessException
+    {
+        ArrayList<CdmaSmsCbProgramResults> results = bData.serviceCategoryProgramResults;
+        outStream.write(8, (results.size() * 4));   // 4 octets per program result
+        for (CdmaSmsCbProgramResults result : results) {
+            int category = result.getCategory();
+            outStream.write(8, category >> 8);
+            outStream.write(8, category);
+            outStream.write(8, result.getLanguage());
+            outStream.write(4, result.getCategoryResult());
+            outStream.skip(4);
+        }
+    }
+
     /**
      * Create serialized representation for BearerData object.
      * (See 3GPP2 C.R1001-F, v1.0, section 4.5 for layout details)
@@ -916,6 +936,10 @@
                 outStream.write(8, SUBPARAM_MESSAGE_STATUS);
                 encodeMsgStatus(bData, outStream);
             }
+            if (bData.serviceCategoryProgramResults != null) {
+                outStream.write(8, SUBPARAM_SERVICE_CATEGORY_PROGRAM_RESULTS);
+                encodeScpResults(bData, outStream);
+            }
             return outStream.toByteArray();
         } catch (BitwiseOutputStream.AccessException ex) {
             Log.e(LOG_TAG, "BearerData encode failed: " + ex);
@@ -1638,7 +1662,7 @@
         while (paramBits >= CATEGORY_FIELD_MIN_SIZE) {
             int operation = inStream.read(4);
             int category = (inStream.read(8) << 8) | inStream.read(8);
-            String language = getLanguageCodeForValue(inStream.read(8));
+            int language = inStream.read(8);
             int maxMessages = inStream.read(8);
             int alertOption = inStream.read(4);
             int numFields = inStream.read(8);
diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsCbTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsCbTest.java
index d2faceb..a95f60c 100644
--- a/telephony/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsCbTest.java
+++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsCbTest.java
@@ -635,7 +635,7 @@
         assertEquals(CdmaSmsCbProgramData.OPERATION_ADD_CATEGORY, programData.getOperation());
         assertEquals(SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT, programData.getCategory());
         assertEquals(CAT_EXTREME_THREAT, programData.getCategoryName());
-        assertEquals("en", programData.getLanguageCode());
+        assertEquals(BearerData.LANGUAGE_ENGLISH, programData.getLanguage());
         assertEquals(100, programData.getMaxMessages());
         assertEquals(CdmaSmsCbProgramData.ALERT_OPTION_DEFAULT_ALERT, programData.getAlertOption());
     }
@@ -692,7 +692,7 @@
         assertEquals(CdmaSmsCbProgramData.OPERATION_DELETE_CATEGORY, programData.getOperation());
         assertEquals(SmsEnvelope.SERVICE_CATEGORY_CMAS_SEVERE_THREAT, programData.getCategory());
         assertEquals(CAT_SEVERE_THREAT, programData.getCategoryName());
-        assertEquals("en", programData.getLanguageCode());
+        assertEquals(BearerData.LANGUAGE_ENGLISH, programData.getLanguage());
         assertEquals(0, programData.getMaxMessages());
         assertEquals(CdmaSmsCbProgramData.ALERT_OPTION_NO_ALERT, programData.getAlertOption());
 
@@ -701,7 +701,7 @@
         assertEquals(SmsEnvelope.SERVICE_CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY,
                 programData.getCategory());
         assertEquals(CAT_AMBER_ALERTS, programData.getCategoryName());
-        assertEquals("en", programData.getLanguageCode());
+        assertEquals(BearerData.LANGUAGE_ENGLISH, programData.getLanguage());
         assertEquals(0, programData.getMaxMessages());
         assertEquals(CdmaSmsCbProgramData.ALERT_OPTION_NO_ALERT, programData.getAlertOption());
     }