Merge "Fix typo on db version upgrade" am: 05f73f5a45 am: ebb89e6aa9
am: 8031dc6e8f

Change-Id: I5a07f15be1be6e9a77df75681dd82348f88c0972
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 9ac0815..578067e 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -66,6 +66,13 @@
                   android:singleUser="true"
                   android:readPermission="android.permission.READ_SMS" />
 
+        <provider android:name="SmsChangesProvider"
+                  android:authorities="sms-changes"
+                  android:multiprocess="false"
+                  android:exported="true"
+                  android:singleUser="true"
+                  android:readPermission="android.permission.READ_SMS" />
+
         <!-- This is a singleton provider that is used by all users.
              A new instance is not created for each user. And the db is shared
              as well.
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 1c53b15..309a57b 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -17,5 +17,5 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" product="tablet" msgid="9194799012395299737">"تهيئة شبكة الجوال"</string>
-    <string name="app_label" product="default" msgid="8338087656149558019">"سعة تخزينية للهاتف والرسائل"</string>
+    <string name="app_label" product="default" msgid="8338087656149558019">"مساحة تخزين للهاتف والرسائل"</string>
 </resources>
diff --git a/res/values-as/config.xml b/res/values-as/config.xml
new file mode 100644
index 0000000..99877a6
--- /dev/null
+++ b/res/values-as/config.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="persist_apns_for_plmn">
+    <item msgid="6413072509259000954">"20404"</item>
+    <item msgid="5639159280778239123">"310004"</item>
+    <item msgid="3860605521380788028">"310120"</item>
+    <item msgid="537693705785480198">"311480"</item>
+  </string-array>
+</resources>
diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml
new file mode 100644
index 0000000..6994d18
--- /dev/null
+++ b/res/values-as/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2008 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_label" product="tablet" msgid="9194799012395299737">"ম’বাইল নেটৱৰ্ক কনফিগাৰেশ্বন"</string>
+    <string name="app_label" product="default" msgid="8338087656149558019">"ফ\'ন আৰু বাৰ্তাৰ সঞ্চয়াগাৰ"</string>
+</resources>
diff --git a/res/values-en-rXC/config.xml b/res/values-en-rXC/config.xml
index 274d8aa..5fadb9d 100644
--- a/res/values-en-rXC/config.xml
+++ b/res/values-en-rXC/config.xml
@@ -2,9 +2,9 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
   <string-array name="persist_apns_for_plmn">
-    <item msgid="6413072509259000954">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‏‏‏‎‎‎‎‎‏‎‎‎‎‏‎‎‏‏‎‏‎‎‏‎‏‎‏‏‎‎‎‏‏‏‏‎‏‎‎20404‎‏‎‎‏‎"</item>
-    <item msgid="5639159280778239123">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‎‎‎‎‏‎‎‏‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‎‎‎‏‎‏‎‏‎‎‎‏‎‎‏‎‏‏‏‎‎‏‎‎‏‎‎‏‏‎310004‎‏‎‎‏‎"</item>
-    <item msgid="3860605521380788028">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‏‎‎‏‎‎‏‏‏‎‏‎‎‎‎‎‎‏‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‎‎‎‎‎‏‎‎‎‏‏‏‎‎‏‏‏‏‎‎‎310120‎‏‎‎‏‎"</item>
-    <item msgid="537693705785480198">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‏‏‎‏‏‎‎‏‎‎‎‏‎‏‏‎‎‏‎‎‏‏‏‎‎‏‏‎‏‏‎‏‎‎‏‏‏‎‏‎‎‏‎‏‎‎‎‎‎‎‎‏‏‎‎311480‎‏‎‎‏‎"</item>
+    <item msgid="6413072509259000954">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‏‏‏‎‎‎‎‎‏‎‎‎‎‏‎‎‏‏‎‏‎‎‏‎‏‎‏‏‎‎‎‏‏‏‏‎‏‎‎20404‎‏‎‎‏‎"</item>
+    <item msgid="5639159280778239123">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‎‎‎‎‏‎‎‏‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‎‎‎‏‎‏‎‏‎‎‎‏‎‎‏‎‏‏‏‎‎‏‎‎‏‎‎‏‏‎310004‎‏‎‎‏‎"</item>
+    <item msgid="3860605521380788028">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‏‎‎‏‎‎‏‏‏‎‏‎‎‎‎‎‎‏‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‎‎‎‎‎‏‎‎‎‏‏‏‎‎‏‏‏‏‎‎‎310120‎‏‎‎‏‎"</item>
+    <item msgid="537693705785480198">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‏‏‎‏‏‎‎‏‎‎‎‏‎‏‏‎‎‏‎‎‏‏‏‎‎‏‏‎‏‏‎‏‎‎‏‏‏‎‏‎‎‏‎‏‎‎‎‎‎‎‎‏‏‎‎311480‎‏‎‎‏‎"</item>
   </string-array>
 </resources>
diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml
index 22950f7..e40d9ab 100644
--- a/res/values-en-rXC/strings.xml
+++ b/res/values-en-rXC/strings.xml
@@ -16,6 +16,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" product="tablet" msgid="9194799012395299737">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‎‏‏‏‏‏‎‎‏‏‏‏‏‏‎‎‎‏‎‏‎‎‏‎‏‏‏‎‏‏‏‏‎‎‏‏‎‎‏‏‏‎‎‏‏‎‎‏‎Mobile Network Configuration‎‏‎‎‏‎"</string>
-    <string name="app_label" product="default" msgid="8338087656149558019">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‎‏‏‎‏‏‎‏‎‏‏‎‏‎‎‎‏‎‏‏‏‏‎‏‎‎‏‎‏‏‎‏‏‏‎‏‎‎‏‎‎‎‏‏‎‎‎‎‎‎‏‏‎Phone and Messaging Storage‎‏‎‎‏‎"</string>
+    <string name="app_label" product="tablet" msgid="9194799012395299737">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‎‏‏‏‏‏‎‎‏‏‏‏‏‏‎‎‎‏‎‏‎‎‏‎‏‏‏‎‏‏‏‏‎‎‏‏‎‎‏‏‏‎‎‏‏‎‎‏‎Mobile Network Configuration‎‏‎‎‏‎"</string>
+    <string name="app_label" product="default" msgid="8338087656149558019">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‎‏‏‎‏‏‎‏‎‏‏‎‏‎‎‎‏‎‏‏‏‏‎‏‎‎‏‎‏‏‎‏‏‏‎‏‎‎‏‎‎‎‏‏‎‎‎‎‎‎‏‏‎Phone and Messaging Storage‎‏‎‎‏‎"</string>
 </resources>
diff --git a/res/values-or/config.xml b/res/values-or/config.xml
new file mode 100644
index 0000000..99877a6
--- /dev/null
+++ b/res/values-or/config.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="persist_apns_for_plmn">
+    <item msgid="6413072509259000954">"20404"</item>
+    <item msgid="5639159280778239123">"310004"</item>
+    <item msgid="3860605521380788028">"310120"</item>
+    <item msgid="537693705785480198">"311480"</item>
+  </string-array>
+</resources>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
new file mode 100644
index 0000000..b004c4f
--- /dev/null
+++ b/res/values-or/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2008 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_label" product="tablet" msgid="9194799012395299737">"ମୋବାଇଲ୍ ନେଟ୍‌ୱର୍କ କନଫିଗରେଶନ୍"</string>
+    <string name="app_label" product="default" msgid="8338087656149558019">"ଫୋନ୍ ଓ ମେସେଜିଙ୍ଗ ଷ୍ଟୋରେଜ୍"</string>
+</resources>
diff --git a/src/com/android/providers/telephony/CarrierIdProvider.java b/src/com/android/providers/telephony/CarrierIdProvider.java
index a2c924c..013db19 100644
--- a/src/com/android/providers/telephony/CarrierIdProvider.java
+++ b/src/com/android/providers/telephony/CarrierIdProvider.java
@@ -330,6 +330,7 @@
          */
         public CarrierIdDatabaseHelper(Context context) {
             super(context, DATABASE_NAME, null, DATABASE_VERSION);
+            Log.d(TAG, "CarrierIdDatabaseHelper: " + DATABASE_VERSION);
             setWriteAheadLoggingEnabled(false);
         }
 
@@ -607,7 +608,7 @@
         if (!SubscriptionController.getInstance().isActiveSubId(subId)) {
             // Remove absent subId from the currentSubscriptionMap.
             final List activeSubscriptions = Arrays.asList(SubscriptionController.getInstance()
-                    .getActiveSubIdList());
+                    .getActiveSubIdList(false));
             int count = 0;
             for (int subscription : mCurrentSubscriptionMap.keySet()) {
                 if (!activeSubscriptions.contains(subscription)) {
diff --git a/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java b/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
index 3d3711a..5fc36d2 100644
--- a/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
+++ b/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
@@ -24,6 +24,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
 import android.database.Cursor;
 import android.database.DatabaseErrorHandler;
 import android.database.DefaultDatabaseErrorHandler;
@@ -292,12 +293,12 @@
         mContext = context;
         // Memory optimization - close idle connections after 30s of inactivity
         setIdleConnectionTimeout(IDLE_CONNECTION_TIMEOUT_MS);
+        setWriteAheadLoggingEnabled(false);
         try {
             PhoneFactory.addLocalLog(TAG, 100);
         } catch (IllegalArgumentException e) {
             // ignore
         }
-        setWriteAheadLoggingEnabled(false);
     }
 
     private static synchronized MmsSmsDatabaseErrorHandler getDbErrorHandler(Context context) {
@@ -1068,6 +1069,29 @@
                    Sms.TYPE + "=" + Sms.MESSAGE_TYPE_INBOX +
                    " OR " +
                    Sms.TYPE + "=" + Sms.MESSAGE_TYPE_SENT + ";");
+
+        if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
+            // Create a table to keep track of changes to SMS table - specifically on update to read
+            // and deletion of msgs
+            db.execSQL("CREATE TABLE sms_changes (" +
+                       "_id INTEGER PRIMARY KEY," +
+                       "orig_rowid INTEGER," +
+                       "sub_id INTEGER," +
+                       "type INTEGER," +
+                       "new_read_status INTEGER" +
+                       ");");
+            db.execSQL("CREATE TRIGGER sms_update_on_read_change_row " +
+                        "AFTER UPDATE OF read ON sms WHEN NEW.read != OLD.read " +
+                        "BEGIN " +
+                        "  INSERT INTO sms_changes VALUES(null, NEW._id, NEW.sub_id, " +
+                        "0, NEW.read); " +
+                        "END;");
+            db.execSQL("CREATE TRIGGER sms_delete_change_row " +
+                       "AFTER DELETE ON sms " +
+                       "BEGIN " +
+                       "  INSERT INTO sms_changes values(null, OLD._id, OLD.sub_id, 1, null); " +
+                       "END;");
+        }
     }
 
     @VisibleForTesting
diff --git a/src/com/android/providers/telephony/SmsChangesProvider.java b/src/com/android/providers/telephony/SmsChangesProvider.java
new file mode 100644
index 0000000..3f14e2b
--- /dev/null
+++ b/src/com/android/providers/telephony/SmsChangesProvider.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2018 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 com.android.providers.telephony;
+
+import android.app.AppOpsManager;
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.UriMatcher;
+import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.database.sqlite.SQLiteQueryBuilder;
+import android.net.Uri;
+import android.util.Log;
+
+/**
+ * This is the ContentProvider for the table sms_changes.
+ * This provider is applicable only for Android Auto builds as
+ * this table exists only in Android Auto environment.
+ *
+ * This provider does not notify of changes.
+ * Interested observers should instead listen to notification on sms table, instead.
+ */
+public class SmsChangesProvider extends ContentProvider {
+    private final static String TAG = "SmsChangesProvider";
+
+    private static final String TABLE_SMS_CHANGES = "sms_changes";
+
+    // Db open helper for tables stored in CE(Credential Encrypted) storage.
+    private SQLiteOpenHelper mCeOpenHelper;
+
+    @Override
+    public String getType(Uri url) {
+        return null;
+    }
+
+    @Override
+    public boolean onCreate() {
+        setAppOps(AppOpsManager.OP_READ_SMS, AppOpsManager.OP_WRITE_SMS);
+        mCeOpenHelper = MmsSmsDatabaseHelper.getInstanceForCe(getContext());
+        return true;
+    }
+
+
+    @Override
+    public Cursor query(Uri url, String[] projectionIn, String selection,
+            String[] selectionArgs, String sort) {
+        // return if FEATURE_AUTOMOTIVE is not set
+        if (!isAutoFeatureSet()) {
+            return null;
+        }
+
+        // Only support one type of query
+        //  Caller sends content://mms-sms and other params
+        if (!isUrlSupported(url)) {
+            return null;
+        }
+
+        SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
+        qb.setTables(TABLE_SMS_CHANGES);
+        SQLiteDatabase db = mCeOpenHelper.getReadableDatabase();
+        return qb.query(db, projectionIn, selection, selectionArgs,
+                null /* groupBy */, null /* having */,
+                null /* sortOrder */);
+    }
+
+    @Override
+    public Uri insert(Uri url, ContentValues initialValues) {
+        return null;
+    }
+
+    @Override
+    public int delete(Uri url, String where, String[] whereArgs) {
+        // return if FEATURE_AUTOMOTIVE is not set
+        if (!isAutoFeatureSet()) {
+            return 0;
+        }
+
+        // only support deletion of all data from the table
+        if (!isUrlSupported(url)) return 0;
+
+        return mCeOpenHelper.getWritableDatabase().delete(TABLE_SMS_CHANGES,
+                null /* whereClause */, null /* whereArgs */);
+    }
+
+    private boolean isUrlSupported(Uri url) {
+        if (sURLMatcher.match(url) != SMSCHANGES_URL) {
+            Log.e(TAG, "Invalid or Unsupported request: " + url);
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public int update(Uri url, ContentValues values, String where, String[] whereArgs) {
+        return 0;
+    }
+
+    private boolean isAutoFeatureSet() {
+        return getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
+    }
+
+    private static final int SMSCHANGES_URL = 0;
+
+    private static final UriMatcher sURLMatcher =
+            new UriMatcher(UriMatcher.NO_MATCH);
+
+    static {
+        sURLMatcher.addURI("sms-changes", null, SMSCHANGES_URL);
+    }
+}
diff --git a/src/com/android/providers/telephony/SmsProvider.java b/src/com/android/providers/telephony/SmsProvider.java
index 95db869..7d556a7 100644
--- a/src/com/android/providers/telephony/SmsProvider.java
+++ b/src/com/android/providers/telephony/SmsProvider.java
@@ -16,6 +16,9 @@
 
 package com.android.providers.telephony;
 
+import static android.app.AppOpsManager.MODE_ALLOWED;
+import static android.app.AppOpsManager.MODE_IGNORED;
+
 import android.annotation.NonNull;
 import android.app.AppOpsManager;
 import android.content.ContentProvider;
@@ -33,6 +36,7 @@
 import android.os.Binder;
 import android.os.UserHandle;
 import android.provider.Contacts;
+import android.provider.Settings;
 import android.provider.Telephony;
 import android.provider.Telephony.MmsSms;
 import android.provider.Telephony.Sms;
@@ -842,6 +846,19 @@
         }
     }
 
+    /** @hide */
+    @Override
+    protected int interpretDefaultAppOpMode(int op) {
+        if (op == AppOpsManager.OP_WRITE_SMS) {
+            return MODE_IGNORED;
+        } else {
+            boolean accessRestrictionEnabled = Settings.Global.getInt(
+                    getContext().getContentResolver(),
+                    Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED, 0) == 1;
+            return accessRestrictionEnabled ? MODE_IGNORED : MODE_ALLOWED;
+        }
+    }
+
     // Db open helper for tables stored in CE(Credential Encrypted) storage.
     @VisibleForTesting
     public SQLiteOpenHelper mCeOpenHelper;
diff --git a/src/com/android/providers/telephony/TelephonyBackupAgent.java b/src/com/android/providers/telephony/TelephonyBackupAgent.java
index 5f6eb10..437b5a2 100644
--- a/src/com/android/providers/telephony/TelephonyBackupAgent.java
+++ b/src/com/android/providers/telephony/TelephonyBackupAgent.java
@@ -16,11 +16,6 @@
 
 package com.android.providers.telephony;
 
-import com.google.android.mms.ContentType;
-import com.google.android.mms.pdu.CharacterSets;
-
-import com.android.internal.annotations.VisibleForTesting;
-
 import android.annotation.TargetApi;
 import android.app.AlarmManager;
 import android.app.IntentService;
@@ -53,6 +48,11 @@
 import android.util.Log;
 import android.util.SparseArray;
 
+import com.android.internal.annotations.VisibleForTesting;
+
+import com.google.android.mms.ContentType;
+import com.google.android.mms.pdu.CharacterSets;
+
 import java.io.BufferedWriter;
 import java.io.File;
 import java.io.FileDescriptor;
@@ -319,7 +319,7 @@
         final SubscriptionManager subscriptionManager = SubscriptionManager.from(this);
         if (subscriptionManager != null) {
             final List<SubscriptionInfo> subInfo =
-                    subscriptionManager.getActiveSubscriptionInfoList();
+                    subscriptionManager.getActiveSubscriptionInfoList(/* userVisibleonly */false);
             if (subInfo != null) {
                 for (SubscriptionInfo sub : subInfo) {
                     final String phoneNumber = getNormalizedNumber(sub);
@@ -1155,8 +1155,12 @@
             values.put(Telephony.Mms.Part.NAME, srcName);
             values.put(Telephony.Mms.Part.CONTENT_ID, "<"+srcName+">");
             values.put(Telephony.Mms.Part.CONTENT_LOCATION, srcName);
-            values.put(Telephony.Mms.Part.CHARSET, mms.body.charSet);
-            values.put(Telephony.Mms.Part.TEXT, mms.body.text);
+
+            values.put(
+                    Telephony.Mms.Part.CHARSET,
+                    mms.body == null ? CharacterSets.DEFAULT_CHARSET : mms.body.charSet);
+            values.put(Telephony.Mms.Part.TEXT, mms.body == null ? "" : mms.body.text);
+
             if (mContentResolver.insert(partUri, values) == null) {
                 if (DEBUG) {
                     Log.e(TAG, "Could not insert body part");
diff --git a/src/com/android/providers/telephony/TelephonyProvider.java b/src/com/android/providers/telephony/TelephonyProvider.java
index 1c71e00..0cf9689 100644
--- a/src/com/android/providers/telephony/TelephonyProvider.java
+++ b/src/com/android/providers/telephony/TelephonyProvider.java
@@ -1891,7 +1891,7 @@
             addIntAttribute(parser, "max_conns_time", map, TIME_LIMIT_FOR_MAX_CONNECTIONS);
             addIntAttribute(parser, "mtu", map, MTU);
             addIntAttribute(parser, "apn_set_id", map, APN_SET_ID);
-
+            addIntAttribute(parser, "carrier_id", map, CARRIER_ID);
 
             addBoolAttribute(parser, "carrier_enabled", map, CARRIER_ENABLED);
             addBoolAttribute(parser, "modem_cognitive", map, MODEM_PERSIST);
diff --git a/tests/src/com/android/providers/telephony/TelephonyBackupAgentTest.java b/tests/src/com/android/providers/telephony/TelephonyBackupAgentTest.java
index 49106ee..37cf6e3 100644
--- a/tests/src/com/android/providers/telephony/TelephonyBackupAgentTest.java
+++ b/tests/src/com/android/providers/telephony/TelephonyBackupAgentTest.java
@@ -40,6 +40,8 @@
 import android.util.Log;
 import android.util.SparseArray;
 
+import com.google.android.mms.pdu.CharacterSets;
+
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
@@ -74,6 +76,8 @@
     private final List<ContentValues> mMmsTable = new ArrayList<>();
     /* Table contains parts, addresses of mms */
     private final List<ContentValues> mMmsAllContentValues = new ArrayList<>();
+    /* Table contains parts, addresses of mms for null body test case */
+    private final List<ContentValues> mMmsNullBodyContentValues = new ArrayList<>();
     /* Cursors being used to access sms, mms tables */
     private FakeCursor mSmsCursor, mMmsCursor;
     /* Test data with sms and mms */
@@ -81,7 +85,7 @@
     /* Json representation for the test data */
     private String[] mSmsJson, mMmsJson, mMmsAttachmentJson;
     /* sms, mms json concatenated as json array */
-    private String mAllSmsJson, mAllMmsJson, mMmsAllAttachmentJson;
+    private String mAllSmsJson, mAllMmsJson, mMmsAllAttachmentJson, mMmsAllNullBodyJson;
 
     private StringWriter mStringWriter;
 
@@ -169,7 +173,7 @@
                 new String[]{"+111 (111) 11111111", "+11121212", "example@example.com",
                         "+999999999"} /*addresses*/,
                 3 /*threadId*/, false /*read*/, null /*smil*/, null /*attachmentTypes*/,
-                null /*attachmentFilenames*/);
+                null /*attachmentFilenames*/, mMmsAllContentValues);
 
         mMmsJson[0] = "{\"self_phone\":\"+111111111111111\",\"sub\":\"Subject 1\"," +
                 "\"date\":\"111111\",\"date_sent\":\"111112\",\"m_type\":\"3\",\"v\":\"17\"," +
@@ -191,7 +195,7 @@
                 121 /*body charset*/,
                 new String[]{"+7 (333) ", "example@example.com", "+999999999"} /*addresses*/,
                 4 /*threadId*/, true /*read*/, null /*smil*/, null /*attachmentTypes*/,
-                null /*attachmentFilenames*/);
+                null /*attachmentFilenames*/, mMmsAllContentValues);
         mMmsJson[1] = "{\"date\":\"111122\",\"date_sent\":\"1111112\",\"m_type\":\"4\"," +
                 "\"v\":\"18\",\"msg_box\":\"222\",\"ct_l\":\"location 2\"," +
                 "\"recipients\":[\"example@example.com\",\"+999999999\"]," +
@@ -210,7 +214,7 @@
                 131 /*body charset*/,
                 new String[]{"333 333333333333", "+1232132214124"} /*addresses*/,
                 1 /*threadId*/, false /*read*/, null /*smil*/, null /*attachmentTypes*/,
-                null /*attachmentFilenames*/);
+                null /*attachmentFilenames*/, mMmsAllContentValues);
 
         mMmsJson[2] = "{\"self_phone\":\"+333333333333333\",\"sub\":\"Subject 10\"," +
                 "\"date\":\"111133\",\"date_sent\":\"1111132\",\"m_type\":\"5\",\"v\":\"19\"," +
@@ -239,7 +243,7 @@
                         + " width='100%'/></layout></head><body><par dur='5000ms'>"
                         + "<img src='image000000.jpg' region='Image' /></par></body></smil>",
                 new String[] {"image/jpg"} /*attachmentTypes*/,
-                new String[] {"GreatPict.jpg"}  /*attachmentFilenames*/);
+                new String[] {"GreatPict.jpg"}  /*attachmentFilenames*/, mMmsAllContentValues);
 
         mMmsAttachmentJson[0] = "{\"self_phone\":\"+111111111111111\",\"sub\":\"Subject 1\"," +
                 "\"date\":\"111111\",\"date_sent\":\"111112\",\"m_type\":\"3\",\"v\":\"17\"," +
@@ -255,6 +259,20 @@
 
         mMmsAllAttachmentJson = makeJsonArray(mMmsAttachmentJson);
 
+        createMmsRow(10 /*id*/, 1 /*subid*/, "Subject 1" /*subject*/,
+                100 /*subcharset*/, 111111 /*date*/, 111112 /*datesent*/, 3 /*type*/,
+                17 /*version*/, 0 /*textonly*/,
+                11 /*msgBox*/, "location 1" /*contentLocation*/, "" /*body*/,
+                CharacterSets.DEFAULT_CHARSET /*body charset*/, new String[] {} /*addresses*/,
+                3 /*threadId*/, false /*read*/, null /*smil*/, null /*attachmentTypes*/,
+                null /*attachmentFilenames*/, mMmsNullBodyContentValues);
+
+        mMmsAllNullBodyJson = makeJsonArray(new String[] {"{\"self_phone\":\"+111111111111111\"," +
+                "\"sub\":\"Subject 1\",\"date\":\"111111\",\"date_sent\":\"111112\",\"m_type\":" +
+                "\"3\",\"v\":\"17\",\"msg_box\":\"11\",\"ct_l\":\"location 1\"," +
+                "\"recipients\":[\"+11121212\",\"example@example.com\",\"+999999999\"]," +
+                "\"read\":\"0\", \"mms_addresses\":[],\"mms_charset\":111,\"sub_cs\":\"100\"}"});
+
 
         ContentProvider contentProvider = new MockContentProvider() {
             @Override
@@ -341,7 +359,8 @@
                                        String contentLocation, String body,
                                        int bodyCharset, String[] addresses, long threadId,
                                        boolean read, String smil, String[] attachmentTypes,
-                                       String[] attachmentFilenames) {
+                                       String[] attachmentFilenames,
+                                       List<ContentValues> rowsContainer) {
         ContentValues mmsRow = new ContentValues();
         mmsRow.put(Telephony.Mms._ID, id);
         mmsRow.put(Telephony.Mms.SUBSCRIPTION_ID, subId);
@@ -364,8 +383,8 @@
         final Uri partUri = Telephony.Mms.CONTENT_URI.buildUpon().appendPath(String.valueOf(id)).
                 appendPath("part").build();
         mCursors.put(partUri, createBodyCursor(body, bodyCharset, smil, attachmentTypes,
-                attachmentFilenames));
-        mMmsAllContentValues.add(mmsRow);
+                attachmentFilenames, rowsContainer));
+        rowsContainer.add(mmsRow);
 
         final Uri addrUri = Telephony.Mms.CONTENT_URI.buildUpon().appendPath(String.valueOf(id)).
                 appendPath("addr").build();
@@ -380,7 +399,8 @@
 
     // Cursor with parts of Mms.
     private FakeCursor createBodyCursor(String body, int charset, String existingSmil,
-            String[] attachmentTypes, String[] attachmentFilenames) {
+            String[] attachmentTypes, String[] attachmentFilenames,
+            List<ContentValues> rowsContainer) {
         List<ContentValues> table = new ArrayList<>();
         final String srcName = String.format("text.%06d.txt", 0);
         final String smilBody = TextUtils.isEmpty(existingSmil) ?
@@ -395,7 +415,7 @@
         smilPart.put(Telephony.Mms.Part.CONTENT_ID, "<smil>");
         smilPart.put(Telephony.Mms.Part.CONTENT_LOCATION, "smil.xml");
         smilPart.put(Telephony.Mms.Part.TEXT, smil);
-        mMmsAllContentValues.add(smilPart);
+        rowsContainer.add(smilPart);
 
         // Text part
         final ContentValues bodyPart = new ContentValues();
@@ -407,7 +427,7 @@
         bodyPart.put(Telephony.Mms.Part.CHARSET, charset);
         bodyPart.put(Telephony.Mms.Part.TEXT, body);
         table.add(bodyPart);
-        mMmsAllContentValues.add(bodyPart);
+        rowsContainer.add(bodyPart);
 
         // Attachments
         if (attachmentTypes != null) {
@@ -421,7 +441,7 @@
                 attachmentPart.put(Telephony.Mms.Part.CONTENT_ID, "<"+attachmentFilename+">");
                 attachmentPart.put(Telephony.Mms.Part.CONTENT_LOCATION, attachmentFilename);
                 table.add(attachmentPart);
-                mMmsAllContentValues.add(attachmentPart);
+                rowsContainer.add(attachmentPart);
             }
         }
 
@@ -622,6 +642,17 @@
         assertEquals(7, mmsProvider.getRowsAdded());
     }
 
+    public void testRestoreMmsWithNullBody() throws Exception {
+        JsonReader jsonReader = new JsonReader
+                (new StringReader(addRandomDataToJson(mMmsAllNullBodyJson)));
+        FakeMmsProvider mmsProvider = new FakeMmsProvider(mMmsNullBodyContentValues);
+        mMockContentResolver.addProvider("mms", mmsProvider);
+
+        mTelephonyBackupAgent.putMmsMessagesToProvider(jsonReader);
+
+        assertEquals(3, mmsProvider.getRowsAdded());
+    }
+
     /**
      * Test with quota exceeded. Checking size of the backup before it hits quota and after.
      * It still backs up more than a quota since there is meta-info which matters with small amounts