[automerger skipped] Check dir path before updating permissions. am: 0c3e2ce281 am: 1d0e52fc3f -s ours

am skip reason: Merged-In I2c60cc2cf8f1f6890678d3cd8c6cfdf31356349f with SHA-1 ff2cc0cede is already in history

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/providers/TelephonyProvider/+/19734279

Change-Id: I6b4c0137f1e1b29448bbee0ced15bcc2a80b4328
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/Android.bp b/Android.bp
index eabd567..def7cde 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,9 +1,15 @@
 android_app {
     name: "TelephonyProvider",
     privileged: true,
-    srcs: ["src/**/*.java"],
+    srcs: ["src/**/*.java", "proto/**/*.proto"],
+    asset_dirs: ["assets/latest_carrier_id"],
     platform_apis: true,
     certificate: "platform",
     libs: ["telephony-common"],
-    static_libs: ["android-common"],
+    static_libs: ["android-common", "telephonyprovider-protos"],
+}
+
+filegroup {
+    name: "telephonyprovider-assets-carrierlist",
+    srcs: ["assets/latest_carrier_id/carrier_list.*"],
 }
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 3b95bce..0a9802d 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -26,11 +26,17 @@
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
     <uses-permission android:name="android.permission.USE_RESERVED_DISK" />
 
+    <!-- Used to access PlatformCompat for security fix enforcement -->
+    <uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG" />
+    <uses-permission android:name="android.permission.LOG_COMPAT_CHANGE" />
+
     <protected-broadcast android:name="android.provider.action.EXTERNAL_PROVIDER_CHANGE" />
     <protected-broadcast android:name="android.intent.action.CONTENT_CHANGED" />
 
     <!-- This permission is only used to send the ACTION_EXTERNAL_PROVIDER_CHANGE intent. -->
     <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
+    <!-- Allows accessing the messages on ICC -->
+    <uses-permission android:name="android.permission.ACCESS_MESSAGES_ON_ICC" />
 
     <application android:process="com.android.phone"
                  android:allowClearUserData="false"
@@ -41,6 +47,7 @@
                  android:label="@string/app_label"
                  android:icon="@mipmap/ic_launcher_phone"
                  android:usesCleartextTraffic="true"
+                 android:forceQueryable="true"
                  android:defaultToDeviceProtectedStorage="true"
                  android:directBootAware="true">
 
@@ -50,13 +57,6 @@
                   android:singleUser="true"
                   android:multiprocess="false" />
 
-        <provider android:name="ServiceStateProvider"
-                  android:authorities="service-state"
-                  android:exported="true"
-                  android:singleUser="true"
-                  android:writePermission="android.permission.MODIFY_PHONE_STATE"
-                  android:multiprocess="false" />
-
         <!-- 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. -->
@@ -107,12 +107,6 @@
                   android:multiprocess="false"
                   android:writePermission="android.permission.MODIFY_PHONE_STATE" />
 
-        <provider android:name="CellBroadcastProvider"
-                  android:authorities="cellbroadcasts_fwk"
-                  android:exported="true"
-                  android:singleUser="true"
-                  android:multiprocess="false" />
-
         <provider android:name="HbpcdLookupProvider"
                   android:authorities="hbpcd_lookup"
                   android:exported="true"
@@ -126,12 +120,6 @@
                   android:singleUser="true"
                   android:multiprocess="false" />
 
-        <provider android:name="RcsProvider"
-                  android:authorities="rcs"
-                  android:multiprocess="false"
-                  android:exported="false"
-                  android:singleUser="true" />
-
         <service
             android:name=".TelephonyBackupAgent$DeferredSmsMmsRestoreService"
             android:exported="false" />
diff --git a/OWNERS b/OWNERS
index 92458db..3059d4d 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,12 +1,15 @@
 amitmahajan@google.com
+breadley@google.com
 fionaxu@google.com
 jackyu@google.com
+hallliu@google.com
 rgreenwalt@google.com
-refuhoo@google.com
-mpq@google.com
+tgunn@google.com
 jminjie@google.com
 shuoq@google.com
-hallliu@google.com
-tgunn@google.com
-breadley@google.com
+refuhoo@google.com
 nazaninb@google.com
+sarahchin@google.com
+dbright@google.com
+xiaotonj@google.com
+
diff --git a/TEST_MAPPING b/TEST_MAPPING
new file mode 100644
index 0000000..0d8db52
--- /dev/null
+++ b/TEST_MAPPING
@@ -0,0 +1,23 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsTelephonyProviderTestCases"
+    },
+    {
+      "name": "TeleServiceTests",
+      "options": [
+        {
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
+        }
+      ]
+    },
+    {
+      "name": "TelephonyProviderTests",
+      "options": [
+        {
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
+        }
+      ]
+    }
+  ]
+}
diff --git a/assets/latest_carrier_id/carrier_list.pb b/assets/latest_carrier_id/carrier_list.pb
new file mode 100644
index 0000000..12ec024
--- /dev/null
+++ b/assets/latest_carrier_id/carrier_list.pb
Binary files differ
diff --git a/assets/latest_carrier_id/carrier_list.textpb b/assets/latest_carrier_id/carrier_list.textpb
new file mode 100644
index 0000000..0d8cb87
--- /dev/null
+++ b/assets/latest_carrier_id/carrier_list.textpb
Binary files differ
diff --git a/assets/sdk28_carrier_id/carrier_list.pb b/assets/sdk28_carrier_id/carrier_list.pb
index 856c5bc..700eb89 100644
--- a/assets/sdk28_carrier_id/carrier_list.pb
+++ b/assets/sdk28_carrier_id/carrier_list.pb
Binary files differ
diff --git a/assets/sdk28_carrier_id/carrier_list.textpb b/assets/sdk28_carrier_id/carrier_list.textpb
index 23196a5..619d989 100644
--- a/assets/sdk28_carrier_id/carrier_list.textpb
+++ b/assets/sdk28_carrier_id/carrier_list.textpb
Binary files differ
diff --git a/assets/carrier_list.pb b/assets/sdk29_carrier_id/carrier_list.pb
similarity index 100%
rename from assets/carrier_list.pb
rename to assets/sdk29_carrier_id/carrier_list.pb
Binary files differ
diff --git a/assets/carrier_list.textpb b/assets/sdk29_carrier_id/carrier_list.textpb
similarity index 100%
rename from assets/carrier_list.textpb
rename to assets/sdk29_carrier_id/carrier_list.textpb
Binary files differ
diff --git a/proto/Android.bp b/proto/Android.bp
new file mode 100644
index 0000000..35dcc98
--- /dev/null
+++ b/proto/Android.bp
@@ -0,0 +1,35 @@
+// Copyright (C) 2019 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.
+
+filegroup {
+    name: "telephonyprovider-proto-sources",
+    srcs: ["src/**/*.proto"],
+}
+
+java_library_static {
+    name: "telephonyprovider-protos",
+    proto: {
+        type: "nano",
+        output_params: [
+            "store_unknown_fields=true",
+            "enum_style=java",
+        ],
+    },
+    srcs: [":telephonyprovider-proto-sources"],
+    static_libs: ["libprotobuf-java-nano"],
+    sdk_version: "core_platform",
+    jarjar_rules: "jarjar-rules.txt",
+    // Pin java_version until jarjar is certified to support later versions. http://b/72703434
+    java_version: "1.8",
+}
diff --git a/proto/jarjar-rules.txt b/proto/jarjar-rules.txt
new file mode 100644
index 0000000..4cad1ee
--- /dev/null
+++ b/proto/jarjar-rules.txt
@@ -0,0 +1 @@
+rule com.google.protobuf.nano.** com.android.providers.telephony.protobuf.nano.@1
\ No newline at end of file
diff --git a/proto/src/carrierId.proto b/proto/src/carrierId.proto
new file mode 100644
index 0000000..9d2f29e
--- /dev/null
+++ b/proto/src/carrierId.proto
@@ -0,0 +1,92 @@
+//
+// Copyright (C) 2019 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.
+//
+
+syntax = "proto2";
+
+package carrierIdentification;
+
+option java_package = "com.android.providers.telephony";
+option java_outer_classname = "CarrierIdProto";
+
+// A complete list of carriers
+message CarrierList {
+  // A collection of carriers. one entry for one carrier.
+  repeated CarrierId carrier_id = 1;
+  // Version number of current carrier list
+  optional int32 version = 2;
+};
+
+// CarrierId is the unique representation of a carrier in CID table.
+message CarrierId {
+  // [Optional] A unique canonical number designated to a carrier.
+  optional int32 canonical_id = 1;
+
+  // [Optional] A user-friendly carrier name (not localized).
+  optional string carrier_name = 2;
+
+  // [Optional] Carrier attributes to match a carrier. At least one value is required.
+  repeated CarrierAttribute carrier_attribute = 3;
+
+  // [Optional] A unique canonical number to represent its parent carrier. The parent-child
+  // relationship can be used to differentiate a single carrier by different networks,
+  // by prepaid v.s. postpaid  or even by 4G v.s. 3G plan.
+  optional int32 parent_canonical_id = 4;
+};
+
+// Attributes used to match a carrier.
+// For each field within this message:
+//   - if not set, the attribute is ignored;
+//   - if set, the device must have one of the specified values to match.
+// Match is based on AND between any field that is set and OR for values within a repeated field.
+message CarrierAttribute {
+  // [Optional] The MCC and MNC that map to this carrier. At least one value is required.
+  repeated string mccmnc_tuple = 1;
+
+  // [Optional] Prefix of IMSI (International Mobile Subscriber Identity) in
+  // decimal format. Some digits can be replaced with "x" symbols matching any digit.
+  // Sample values: 20404794, 21670xx2xxx.
+  repeated string imsi_prefix_xpattern = 2;
+
+  // [Optional] The Service Provider Name. Read from subscription EF_SPN.
+  // Sample values: C Spire, LeclercMobile
+  repeated string spn = 3;
+
+  // [Optional] PLMN network name. Read from subscription EF_PNN.
+  // Sample values:
+  repeated string plmn = 4;
+
+  // [Optional] Group Identifier Level1 for a GSM phone. Read from subscription EF_GID1.
+  // Sample values: 6D, BAE0000000000000
+  repeated string gid1 = 5;
+
+  // [Optional] Group Identifier Level2 for a GSM phone. Read from subscription EF_GID2.
+  // Sample values: 6D, BAE0000000000000
+  repeated string gid2 = 6;
+
+  // [Optional] The Access Point Name, corresponding to "apn" field returned by
+  // "content://telephony/carriers/preferapn" on device.
+  // Sample values: fast.t-mobile.com, internet
+  repeated string preferred_apn = 7;
+
+  // [Optional] Prefix of Integrated Circuit Card Identifier. Read from subscription EF_ICCID.
+  // Sample values: 894430, 894410
+  repeated string iccid_prefix = 8;
+
+  // [Optional] Carrier Privilege Access Rule in hex string.
+  // Sample values: 61ed377e85d386a8dfee6b864bd85b0bfaa5af88
+  repeated string privilege_access_rule = 9;
+};
+
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 309a57b..9bcbd19 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/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">"تهيئة شبكة الجوال"</string>
+    <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 44f053d..a3c299f 100644
--- a/src/com/android/providers/telephony/CarrierIdProvider.java
+++ b/src/com/android/providers/telephony/CarrierIdProvider.java
@@ -25,23 +25,23 @@
 import android.content.pm.PackageManager;
 import android.database.Cursor;
 import android.database.MatrixCursor;
-import android.database.SQLException;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteOpenHelper;
 import android.database.sqlite.SQLiteQueryBuilder;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Environment;
+import android.os.FileUtils;
 import android.os.SystemProperties;
 import android.provider.Telephony.CarrierId;
+import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.text.TextUtils;
 import android.util.Log;
-import android.util.Pair;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.telephony.SubscriptionController;
-import com.android.internal.telephony.nano.CarrierIdProto;
+import com.android.internal.telephony.util.TelephonyUtils;
+import com.android.providers.telephony.nano.CarrierIdProto;
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
@@ -54,8 +54,6 @@
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
-import libcore.io.IoUtils;
-
 /**
  * This class provides the ability to query the Carrier Identification databases
  * (A.K.A. cid) which is stored in a SQLite database.
@@ -536,7 +534,7 @@
         } catch (IOException ex) {
             Log.e(TAG, "read carrier list from assets pb failure: " + ex);
         } finally {
-            IoUtils.closeQuietly(is);
+            FileUtils.closeQuietly(is);
         }
         try {
             is = new FileInputStream(new File(Environment.getDataDirectory(), OTA_UPDATED_PB_PATH));
@@ -544,7 +542,7 @@
         } catch (IOException ex) {
             Log.e(TAG, "read carrier list from ota pb failure: " + ex);
         } finally {
-            IoUtils.closeQuietly(is);
+            FileUtils.closeQuietly(is);
         }
 
         // compare version
@@ -553,7 +551,7 @@
             version = assets.version;
         }
         // bypass version check for ota carrier id test
-        if (ota != null && ((Build.IS_DEBUGGABLE && SystemProperties.getBoolean(
+        if (ota != null && ((TelephonyUtils.IS_DEBUGGABLE && SystemProperties.getBoolean(
                 "persist.telephony.test.carrierid.ota", false))
                 || (ota.version > version))) {
             carrierList = ota;
@@ -607,13 +605,21 @@
 
         // Handle DEFAULT_SUBSCRIPTION_ID
         if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
-            subId = SubscriptionController.getInstance().getDefaultSubId();
+            subId = SubscriptionManager.getDefaultSubscriptionId();
         }
 
-        if (!SubscriptionController.getInstance().isActiveSubId(subId)) {
+        SubscriptionManager sm = (SubscriptionManager) getContext().getSystemService(
+            Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+        if (!sm.isActiveSubscriptionId(subId)) {
             // Remove absent subId from the currentSubscriptionMap.
-            final List activeSubscriptions = Arrays.asList(SubscriptionController.getInstance()
-                    .getActiveSubIdList(false));
+            List activeSubscriptions = new ArrayList<>();
+            final List<SubscriptionInfo> subscriptionInfoList =
+                sm.getCompleteActiveSubscriptionInfoList();
+            if (subscriptionInfoList != null) {
+                for (SubscriptionInfo subInfo : subscriptionInfoList) {
+                    activeSubscriptions.add(subInfo.getSubscriptionId());
+                }
+            }
             int count = 0;
             for (int subscription : mCurrentSubscriptionMap.keySet()) {
                 if (!activeSubscriptions.contains(subscription)) {
@@ -633,7 +639,7 @@
 
     private Cursor queryCarrierIdForCurrentSubscription(Uri uri, String[] projectionIn) {
         // Parse the subId, using the default subId if subId is not provided
-        int subId = SubscriptionController.getInstance().getDefaultSubId();
+        int subId = SubscriptionManager.getDefaultSubscriptionId();
         if (!TextUtils.isEmpty(uri.getLastPathSegment())) {
             try {
                 subId = Integer.parseInt(uri.getLastPathSegment());
@@ -645,7 +651,7 @@
 
         // Handle DEFAULT_SUBSCRIPTION_ID
         if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
-            subId = SubscriptionController.getInstance().getDefaultSubId();
+            subId = SubscriptionManager.getDefaultSubscriptionId();
         }
 
         if (!mCurrentSubscriptionMap.containsKey(subId)) {
diff --git a/src/com/android/providers/telephony/CellBroadcastProvider.java b/src/com/android/providers/telephony/CellBroadcastProvider.java
deleted file mode 100644
index 4c8a7e2..0000000
--- a/src/com/android/providers/telephony/CellBroadcastProvider.java
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * Copyright (C) 2019 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.ContentUris;
-import android.content.ContentValues;
-import android.content.Context;
-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.net.Uri;
-import android.os.Binder;
-import android.os.Process;
-import android.provider.Telephony.CellBroadcasts;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.util.Arrays;
-
-/**
- * The content provider that provides access of cell broadcast message to application.
- * Permission {@link android.permission.READ_CELL_BROADCASTS} is required for querying the cell
- * broadcast message. Only phone process has the permission to write/update the database via this
- * provider.
- */
-public class CellBroadcastProvider extends ContentProvider {
-    /** Interface for read/write permission check. */
-    public interface PermissionChecker {
-        /** Return {@code True} if the caller has the permission to write/update the database. */
-        boolean hasWritePermission();
-
-        /** Return {@code True} if the caller has the permission to query the database. */
-        boolean hasReadPermission();
-    }
-
-    private static final String TAG = CellBroadcastProvider.class.getSimpleName();
-
-    private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
-
-    /** Database name. */
-    private static final String DATABASE_NAME = "cellbroadcasts.db";
-
-    /** Database version. */
-    private static final int DATABASE_VERSION = 1;
-
-    /** URI matcher for ContentProvider queries. */
-    private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
-
-    /** URI matcher type to get all cell broadcasts. */
-    private static final int ALL = 0;
-
-    /** MIME type for the list of all cell broadcasts. */
-    private static final String LIST_TYPE = "vnd.android.cursor.dir/cellbroadcast";
-
-    /** Table name of cell broadcast message. */
-    @VisibleForTesting
-    public static final String CELL_BROADCASTS_TABLE_NAME = "cell_broadcasts";
-
-    /** Authority string for content URIs. */
-    @VisibleForTesting
-    public static final String AUTHORITY = "cellbroadcasts_fwk";
-
-    /** Content uri of this provider. */
-    public static final Uri CONTENT_URI = Uri.parse("content://cellbroadcasts_fwk");
-
-    @VisibleForTesting
-    public PermissionChecker mPermissionChecker;
-
-    /** The database helper for this content provider. */
-    @VisibleForTesting
-    public SQLiteOpenHelper mDbHelper;
-
-    static {
-        sUriMatcher.addURI(AUTHORITY, null, ALL);
-    }
-
-    public CellBroadcastProvider() {}
-
-    @VisibleForTesting
-    public CellBroadcastProvider(PermissionChecker permissionChecker) {
-        mPermissionChecker = permissionChecker;
-    }
-
-    @Override
-    public boolean onCreate() {
-        mDbHelper = new CellBroadcastDatabaseHelper(getContext());
-        mPermissionChecker = new CellBroadcastPermissionChecker();
-        setAppOps(AppOpsManager.OP_READ_CELL_BROADCASTS, AppOpsManager.OP_NONE);
-        return true;
-    }
-
-    /**
-     * Return the MIME type of the data at the specified URI.
-     *
-     * @param uri the URI to query.
-     * @return a MIME type string, or null if there is no type.
-     */
-    @Override
-    public String getType(Uri uri) {
-        int match = sUriMatcher.match(uri);
-        switch (match) {
-            case ALL:
-                return LIST_TYPE;
-            default:
-                return null;
-        }
-    }
-
-    @Override
-    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
-            String sortOrder) {
-        checkReadPermission();
-
-        if (DBG) {
-            Log.d(TAG, "query:"
-                    + " uri = " + uri
-                    + " projection = " + Arrays.toString(projection)
-                    + " selection = " + selection
-                    + " selectionArgs = " + Arrays.toString(selectionArgs)
-                    + " sortOrder = " + sortOrder);
-        }
-
-        String orderBy;
-        if (!TextUtils.isEmpty(sortOrder)) {
-            orderBy = sortOrder;
-        } else {
-            orderBy = CellBroadcasts.RECEIVED_TIME + " DESC";
-        }
-
-        int match = sUriMatcher.match(uri);
-        switch (match) {
-            case ALL:
-                return getReadableDatabase().query(
-                        CELL_BROADCASTS_TABLE_NAME, projection, selection, selectionArgs,
-                        null /* groupBy */, null /* having */, orderBy);
-            default:
-                throw new IllegalArgumentException(
-                        "Query method doesn't support this uri = " + uri);
-        }
-    }
-
-    @Override
-    public Uri insert(Uri uri, ContentValues values) {
-        checkWritePermission();
-
-        if (DBG) {
-            Log.d(TAG, "insert:"
-                    + " uri = " + uri
-                    + " contentValue = " + values);
-        }
-
-        switch (sUriMatcher.match(uri)) {
-            case ALL:
-                long row = getWritableDatabase().insertOrThrow(CELL_BROADCASTS_TABLE_NAME, null,
-                        values);
-                if (row > 0) {
-                    Uri newUri = ContentUris.withAppendedId(CONTENT_URI, row);
-                    getContext().getContentResolver()
-                            .notifyChange(CONTENT_URI, null /* observer */);
-                    return newUri;
-                } else {
-                    Log.e(TAG, "Insert record failed because of unknown reason, uri = " + uri);
-                    return null;
-                }
-            default:
-                throw new IllegalArgumentException(
-                        "Insert method doesn't support this uri = " + uri);
-        }
-    }
-
-    @Override
-    public int delete(Uri uri, String selection, String[] selectionArgs) {
-        checkWritePermission();
-
-        if (DBG) {
-            Log.d(TAG, "delete:"
-                    + " uri = " + uri
-                    + " selection = " + selection
-                    + " selectionArgs = " + Arrays.toString(selectionArgs));
-        }
-
-        switch (sUriMatcher.match(uri)) {
-            case ALL:
-                return getWritableDatabase().delete(CELL_BROADCASTS_TABLE_NAME,
-                        selection, selectionArgs);
-            default:
-                throw new IllegalArgumentException(
-                        "Delete method doesn't support this uri = " + uri);
-        }
-    }
-
-    @Override
-    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
-        checkWritePermission();
-
-        if (DBG) {
-            Log.d(TAG, "update:"
-                    + " uri = " + uri
-                    + " values = {" + values + "}"
-                    + " selection = " + selection
-                    + " selectionArgs = " + Arrays.toString(selectionArgs));
-        }
-
-        switch (sUriMatcher.match(uri)) {
-            case ALL:
-                int rowCount = getWritableDatabase().update(
-                        CELL_BROADCASTS_TABLE_NAME,
-                        values,
-                        selection,
-                        selectionArgs);
-                if (rowCount > 0) {
-                    getContext().getContentResolver().notifyChange(uri, null /* observer */);
-                }
-                return rowCount;
-            default:
-                throw new IllegalArgumentException(
-                        "Update method doesn't support this uri = " + uri);
-        }
-    }
-
-    @VisibleForTesting
-    public static String getStringForCellBroadcastTableCreation(String tableName) {
-        return "CREATE TABLE " + tableName + " ("
-                + CellBroadcasts._ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
-                + CellBroadcasts.SUB_ID + " INTEGER,"
-                + CellBroadcasts.GEOGRAPHICAL_SCOPE + " INTEGER,"
-                + CellBroadcasts.PLMN + " TEXT,"
-                + CellBroadcasts.LAC + " INTEGER,"
-                + CellBroadcasts.CID + " INTEGER,"
-                + CellBroadcasts.SERIAL_NUMBER + " INTEGER,"
-                + CellBroadcasts.SERVICE_CATEGORY + " INTEGER,"
-                + CellBroadcasts.LANGUAGE_CODE + " TEXT,"
-                + CellBroadcasts.MESSAGE_BODY + " TEXT,"
-                + CellBroadcasts.MESSAGE_FORMAT + " INTEGER,"
-                + CellBroadcasts.MESSAGE_PRIORITY + " INTEGER,"
-                + CellBroadcasts.ETWS_WARNING_TYPE + " INTEGER,"
-                + CellBroadcasts.CMAS_MESSAGE_CLASS + " INTEGER,"
-                + CellBroadcasts.CMAS_CATEGORY + " INTEGER,"
-                + CellBroadcasts.CMAS_RESPONSE_TYPE + " INTEGER,"
-                + CellBroadcasts.CMAS_SEVERITY + " INTEGER,"
-                + CellBroadcasts.CMAS_URGENCY + " INTEGER,"
-                + CellBroadcasts.CMAS_CERTAINTY + " INTEGER,"
-                + CellBroadcasts.RECEIVED_TIME + " BIGINT,"
-                + CellBroadcasts.MESSAGE_BROADCASTED + " BOOLEAN DEFAULT 0,"
-                + CellBroadcasts.GEOMETRIES + " TEXT,"
-                + CellBroadcasts.MAXIMUM_WAIT_TIME + " INTEGER);";
-    }
-
-    private SQLiteDatabase getWritableDatabase() {
-        return mDbHelper.getWritableDatabase();
-    }
-
-    private SQLiteDatabase getReadableDatabase() {
-        return mDbHelper.getReadableDatabase();
-    }
-
-    private void checkWritePermission() {
-        if (!mPermissionChecker.hasWritePermission()) {
-            throw new SecurityException(
-                    "No permission to write CellBroadcast provider");
-        }
-    }
-
-    private void checkReadPermission() {
-        if (!mPermissionChecker.hasReadPermission()) {
-            throw new SecurityException(
-                    "No permission to read CellBroadcast provider");
-        }
-    }
-
-    private class CellBroadcastDatabaseHelper extends SQLiteOpenHelper {
-        CellBroadcastDatabaseHelper(Context context) {
-            super(context, DATABASE_NAME, null /* factory */, DATABASE_VERSION);
-        }
-
-        @Override
-        public void onCreate(SQLiteDatabase db) {
-            db.execSQL(getStringForCellBroadcastTableCreation(CELL_BROADCASTS_TABLE_NAME));
-        }
-
-        @Override
-        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}
-    }
-
-    private class CellBroadcastPermissionChecker implements PermissionChecker {
-        @Override
-        public boolean hasWritePermission() {
-            // Only the phone process has the write permission to modify this provider. 
-            return Binder.getCallingUid() == Process.PHONE_UID;
-        }
-
-        @Override
-        public boolean hasReadPermission() {
-            // Only the phone process has the read permission to query data from this provider. 
-            return Binder.getCallingUid() == Process.PHONE_UID;
-        }
-    }
-}
diff --git a/src/com/android/providers/telephony/HbpcdLookupDatabaseHelper.java b/src/com/android/providers/telephony/HbpcdLookupDatabaseHelper.java
index 0149687..056738f 100644
--- a/src/com/android/providers/telephony/HbpcdLookupDatabaseHelper.java
+++ b/src/com/android/providers/telephony/HbpcdLookupDatabaseHelper.java
@@ -65,7 +65,6 @@
 import android.database.sqlite.SQLiteQueryBuilder;
 import android.util.Log;
 import android.util.Xml;
-import com.android.internal.util.XmlUtils;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -79,6 +78,7 @@
 import com.android.internal.telephony.HbpcdLookup.MccSidRange;
 import com.android.internal.telephony.HbpcdLookup.ArbitraryMccSidMatch;
 import com.android.internal.telephony.HbpcdLookup.NanpAreaCode;
+import com.android.internal.util.XmlUtils;
 
 public class HbpcdLookupDatabaseHelper extends SQLiteOpenHelper {
     private static final String TAG = "HbpcdLockupDatabaseHelper";
diff --git a/src/com/android/providers/telephony/MmsProvider.java b/src/com/android/providers/telephony/MmsProvider.java
index 6ba775b..1e33313 100644
--- a/src/com/android/providers/telephony/MmsProvider.java
+++ b/src/com/android/providers/telephony/MmsProvider.java
@@ -31,7 +31,6 @@
 import android.database.sqlite.SQLiteQueryBuilder;
 import android.net.Uri;
 import android.os.Binder;
-import android.os.FileUtils;
 import android.os.ParcelFileDescriptor;
 import android.os.UserHandle;
 import android.provider.BaseColumns;
@@ -521,9 +520,13 @@
                         // Give everyone rw permission until we encrypt the file
                         // (in PduPersister.persistData). Once the file is encrypted, the
                         // permissions will be set to 0644.
-                        int result = FileUtils.setPermissions(path, 0666, -1, -1);
-                        if (LOCAL_LOGV) {
-                            Log.d(TAG, "MmsProvider.insert setPermissions result: " + result);
+                        try {
+                            Os.chmod(path, 0666);
+                            if (LOCAL_LOGV) {
+                                Log.d(TAG, "MmsProvider.insert chmod is successful");
+                            }
+                        } catch (ErrnoException e) {
+                            Log.e(TAG, "Exception in chmod: " + e);
                         }
                     } catch (IOException e) {
                         Log.e(TAG, "createNewFile", e);
@@ -818,6 +821,7 @@
             case MMS_PART_RESET_FILE_PERMISSION:
                 String path = getContext().getDir(PARTS_DIR_NAME, 0).getPath() + '/' +
                         uri.getPathSegments().get(1);
+
                 try {
                     String partsDirPath = getContext().getDir(PARTS_DIR_NAME, 0).getCanonicalPath();
                     if (!new File(path).getCanonicalPath().startsWith(partsDirPath)) {
diff --git a/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java b/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
index 7ecfc46..068f209 100644
--- a/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
+++ b/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
@@ -16,7 +16,7 @@
 
 package com.android.providers.telephony;
 
-import static android.provider.Telephony.RcsColumns.IS_RCS_TABLE_SCHEMA_CODE_COMPLETE;
+import static com.android.providers.telephony.SmsProvider.NO_ERROR_CODE;
 
 import android.content.BroadcastReceiver;
 import android.content.ContentValues;
@@ -46,10 +46,10 @@
 import android.provider.Telephony.Threads;
 import android.telephony.SubscriptionManager;
 import android.util.Log;
-import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.PhoneFactory;
+
 import com.google.android.mms.pdu.EncodedStringValue;
 import com.google.android.mms.pdu.PduHeaders;
 
@@ -266,7 +266,7 @@
 
     /**
      * The primary purpose of this DatabaseErrorHandler is to broadcast an intent on corruption and
-     * print a Slog.wtf so database corruption can be caught earlier.
+     * print a Log.wtf so database corruption can be caught earlier.
      */
     private static class MmsSmsDatabaseErrorHandler implements DatabaseErrorHandler {
         private DefaultDatabaseErrorHandler mDefaultDatabaseErrorHandler
@@ -313,7 +313,7 @@
         Intent intent = new Intent(Sms.Intents.ACTION_SMS_MMS_DB_LOST);
         intent.putExtra(Sms.Intents.EXTRA_IS_CORRUPTED, isCorrupted);
         intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
-        context.sendBroadcast(intent, android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+        context.sendBroadcast(intent);
     }
     /**
      * Returns a singleton helper for the combined MMS and SMS database in device encrypted storage.
@@ -539,7 +539,6 @@
                 // disappeared mysteriously?
                 localLogWtf("onCreate: was already called once earlier");
                 intent.putExtra(Intents.EXTRA_IS_INITIAL_CREATE, false);
-                sendDbLostIntent(mContext, false);
             } else {
                 setInitialCreateDone();
                 intent.putExtra(Intents.EXTRA_IS_INITIAL_CREATE, true);
@@ -550,14 +549,6 @@
         createMmsTables(db);
         createSmsTables(db);
         createCommonTables(db);
-
-        if (IS_RCS_TABLE_SCHEMA_CODE_COMPLETE) {
-            RcsProviderThreadHelper.createThreadTables(db);
-            RcsProviderParticipantHelper.createParticipantTables(db);
-            RcsProviderMessageHelper.createRcsMessageTables(db);
-            RcsProviderEventHelper.createRcsEventTables(db);
-        }
-
         createCommonTriggers(db);
         createMmsTriggers(db);
         createWordsTables(db);
@@ -570,7 +561,7 @@
     }
 
     private static void localLogWtf(String logMsg) {
-        Slog.wtf(TAG, logMsg);
+        Log.wtf(TAG, logMsg);
         PhoneFactory.localLog(TAG, logMsg);
     }
 
@@ -1012,7 +1003,7 @@
             "service_center TEXT," +
             "locked INTEGER DEFAULT 0," +
             "sub_id INTEGER DEFAULT " + SubscriptionManager.INVALID_SUBSCRIPTION_ID + ", " +
-            "error_code INTEGER DEFAULT 0," +
+            "error_code INTEGER DEFAULT " + NO_ERROR_CODE + ", " +
             "creator TEXT," +
             "seen INTEGER DEFAULT 0" +
             ");";
@@ -1665,15 +1656,6 @@
                 db.endTransaction();
             }
             // fall through
-        case 67:
-            if (currentVersion <= 67 || !IS_RCS_TABLE_SCHEMA_CODE_COMPLETE) {
-                return;
-            }
-            RcsProviderThreadHelper.createThreadTables(db);
-            RcsProviderParticipantHelper.createParticipantTables(db);
-            RcsProviderMessageHelper.createRcsMessageTables(db);
-            RcsProviderEventHelper.createRcsEventTables(db);
-            return;
         }
 
         Log.e(TAG, "Destroying all old data.");
@@ -1816,7 +1798,7 @@
 
     private void upgradeDatabaseToVersion48(SQLiteDatabase db) {
         // Add 'error_code' column to sms table.
-        db.execSQL("ALTER TABLE sms ADD COLUMN error_code INTEGER DEFAULT 0");
+        db.execSQL("ALTER TABLE sms ADD COLUMN error_code INTEGER DEFAULT " + NO_ERROR_CODE);
     }
 
     private void upgradeDatabaseToVersion51(SQLiteDatabase db) {
diff --git a/src/com/android/providers/telephony/MmsSmsProvider.java b/src/com/android/providers/telephony/MmsSmsProvider.java
index dbf85ae..f5aeadc 100644
--- a/src/com/android/providers/telephony/MmsSmsProvider.java
+++ b/src/com/android/providers/telephony/MmsSmsProvider.java
@@ -305,6 +305,7 @@
     private SQLiteOpenHelper mOpenHelper;
 
     private boolean mUseStrictPhoneNumberComparation;
+    private int mMinMatch;
 
     private static final String METHOD_IS_RESTORING = "is_restoring";
     private static final String IS_RESTORING_KEY = "restoring";
@@ -316,6 +317,9 @@
         mUseStrictPhoneNumberComparation =
             getContext().getResources().getBoolean(
                     com.android.internal.R.bool.config_use_strict_phone_number_comparation);
+        mMinMatch =
+            getContext().getResources().getInteger(
+                    com.android.internal.R.integer.config_phonenumber_compare_min_match);
         TelephonyBackupAgent.DeferredSmsMmsRestoreService.startIfFilesExist(getContext());
         return true;
     }
@@ -552,7 +556,7 @@
             selectionArgs = new String[] { refinedAddress };
         } else {
             selection += " OR PHONE_NUMBERS_EQUAL(address, ?, " +
-                        (mUseStrictPhoneNumberComparation ? 1 : 0) + ")";
+                        (mUseStrictPhoneNumberComparation ? "1)" : "0, " + mMinMatch + ")");
             selectionArgs = new String[] { refinedAddress, refinedAddress };
         }
 
@@ -1007,13 +1011,14 @@
      *   FROM pdu, (SELECT msg_id AS address_msg_id
      *              FROM addr
      *              WHERE (address='<phoneNumber>' OR
-     *              PHONE_NUMBERS_EQUAL(addr.address, '<phoneNumber>', 1/0)))
+     *              PHONE_NUMBERS_EQUAL(addr.address, '<phoneNumber>', 1/0, none/mMinMatch)))
      *             AS matching_addresses
      *   WHERE pdu._id = matching_addresses.address_msg_id
      * UNION
      * SELECT ...
      *   FROM sms
-     *   WHERE (address='<phoneNumber>' OR PHONE_NUMBERS_EQUAL(sms.address, '<phoneNumber>', 1/0));
+     *   WHERE (address='<phoneNumber>' OR
+     *          PHONE_NUMBERS_EQUAL(sms.address, '<phoneNumber>', 1/0, none/mMinMatch));
      */
     private Cursor getMessagesByPhoneNumber(
             String phoneNumber, String[] projection, String selection,
@@ -1028,7 +1033,7 @@
                         selection,
                         "(address=" + escapedPhoneNumber + " OR PHONE_NUMBERS_EQUAL(address, " +
                         escapedPhoneNumber +
-                        (mUseStrictPhoneNumberComparation ? ", 1))" : ", 0))"));
+                        (mUseStrictPhoneNumberComparation ? ", 1))" : ", 0, " + mMinMatch + "))"));
         SQLiteQueryBuilder mmsQueryBuilder = new SQLiteQueryBuilder();
         SQLiteQueryBuilder smsQueryBuilder = new SQLiteQueryBuilder();
 
@@ -1040,7 +1045,7 @@
                 "FROM addr WHERE (address=" + escapedPhoneNumber +
                 " OR PHONE_NUMBERS_EQUAL(addr.address, " +
                 escapedPhoneNumber +
-                (mUseStrictPhoneNumberComparation ? ", 1))) " : ", 0))) ") +
+                (mUseStrictPhoneNumberComparation ? ", 1))) " : ", 0, " + mMinMatch + "))) ") +
                 "AS matching_addresses");
         smsQueryBuilder.setTables(smsTable);
 
diff --git a/src/com/android/providers/telephony/RcsProvider.java b/src/com/android/providers/telephony/RcsProvider.java
deleted file mode 100644
index 3235b27..0000000
--- a/src/com/android/providers/telephony/RcsProvider.java
+++ /dev/null
@@ -1,804 +0,0 @@
-/*
- * 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 static android.provider.Telephony.RcsColumns.RcsThreadColumns.RCS_THREAD_URI_PART;
-import static android.provider.Telephony.RcsColumns.TRANSACTION_FAILED;
-
-import static com.android.providers.telephony.RcsProviderUtil.buildUriWithRowIdAppended;
-import static com.android.providers.telephony.RcsProviderUtil.returnUriAsIsIfSuccessful;
-
-import android.app.AppOpsManager;
-import android.content.ContentProvider;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.UriMatcher;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.CancellationSignal;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-/**
- * Content provider to handle RCS messages. The functionality here is similar to SmsProvider,
- * MmsProvider etc.
- *
- * The provider has constraints around inserting, updating and deleting - the user needs to know
- * whether they are inserting a message that is incoming/outgoing, or the thread they are inserting
- * is a group or p2p etc. This is in order to keep the implementation simple and avoid complex
- * queries.
- *
- * @hide
- */
-public class RcsProvider extends ContentProvider {
-    static final String TAG = "RcsProvider";
-    static final String AUTHORITY = "rcs";
-    private static final String CONTENT_AUTHORITY = "content://" + AUTHORITY;
-
-    private static final Uri PARTICIPANT_URI_PREFIX =
-            Uri.parse(CONTENT_AUTHORITY + "/participant/");
-    private static final Uri P2P_THREAD_URI_PREFIX = Uri.parse(CONTENT_AUTHORITY + "/p2p_thread/");
-    private static final Uri FILE_TRANSFER_PREFIX = Uri.parse(
-            CONTENT_AUTHORITY + "/file_transfer/");
-    static final Uri GROUP_THREAD_URI_PREFIX = Uri.parse(CONTENT_AUTHORITY + "/group_thread/");
-
-    // Rcs table names
-    static final String RCS_THREAD_TABLE = "rcs_thread";
-    static final String RCS_1_TO_1_THREAD_TABLE = "rcs_1_to_1_thread";
-    static final String RCS_GROUP_THREAD_TABLE = "rcs_group_thread";
-    static final String UNIFIED_RCS_THREAD_VIEW = "rcs_unified_rcs_thread_view";
-    static final String RCS_PARTICIPANT_TABLE = "rcs_participant";
-    static final String RCS_PARTICIPANT_THREAD_JUNCTION_TABLE = "rcs_thread_participant";
-    static final String RCS_MESSAGE_TABLE = "rcs_message";
-    static final String RCS_INCOMING_MESSAGE_TABLE = "rcs_incoming_message";
-    static final String RCS_OUTGOING_MESSAGE_TABLE = "rcs_outgoing_message";
-    static final String RCS_MESSAGE_DELIVERY_TABLE = "rcs_message_delivery";
-    static final String UNIFIED_MESSAGE_VIEW = "rcs_unified_message_view";
-    static final String RCS_FILE_TRANSFER_TABLE = "rcs_file_transfer";
-    static final String RCS_THREAD_EVENT_TABLE = "rcs_thread_event";
-    static final String RCS_PARTICIPANT_EVENT_TABLE = "rcs_participant_event";
-    static final String RCS_UNIFIED_EVENT_VIEW = "rcs_unified_event_view";
-
-    private static final UriMatcher URL_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
-
-    private static final int UNIFIED_RCS_THREAD = 1;
-    private static final int UNIFIED_RCS_THREAD_WITH_ID = 2;
-    private static final int PARTICIPANT = 3;
-    private static final int PARTICIPANT_WITH_ID = 4;
-    private static final int PARTICIPANT_ALIAS_CHANGE_EVENT = 5;
-    private static final int PARTICIPANT_ALIAS_CHANGE_EVENT_WITH_ID = 6;
-    private static final int P2P_THREAD = 7;
-    private static final int P2P_THREAD_WITH_ID = 8;
-    private static final int P2P_THREAD_PARTICIPANT = 9;
-    private static final int P2P_THREAD_PARTICIPANT_WITH_ID = 10;
-    private static final int GROUP_THREAD = 11;
-    private static final int GROUP_THREAD_WITH_ID = 12;
-    private static final int GROUP_THREAD_PARTICIPANT = 13;
-    private static final int GROUP_THREAD_PARTICIPANT_WITH_ID = 14;
-    private static final int GROUP_THREAD_PARTICIPANT_JOINED_EVENT = 15;
-    private static final int GROUP_THREAD_PARTICIPANT_JOINED_EVENT_WITH_ID = 16;
-    private static final int GROUP_THREAD_PARTICIPANT_LEFT_EVENT = 17;
-    private static final int GROUP_THREAD_PARTICIPANT_LEFT_EVENT_WITH_ID = 18;
-    private static final int GROUP_THREAD_NAME_CHANGE_EVENT = 19;
-    private static final int GROUP_THREAD_NAME_CHANGE_EVENT_WITH_ID = 20;
-    private static final int GROUP_THREAD_ICON_CHANGE_EVENT = 21;
-    private static final int GROUP_THREAD_ICON_CHANGE_EVENT_WITH_ID = 22;
-    private static final int UNIFIED_MESSAGE = 23;
-    private static final int UNIFIED_MESSAGE_WITH_ID = 24;
-    private static final int UNIFIED_MESSAGE_WITH_FILE_TRANSFER = 25;
-    private static final int INCOMING_MESSAGE = 26;
-    private static final int INCOMING_MESSAGE_WITH_ID = 27;
-    private static final int OUTGOING_MESSAGE = 28;
-    private static final int OUTGOING_MESSAGE_WITH_ID = 29;
-    private static final int OUTGOING_MESSAGE_DELIVERY = 30;
-    private static final int OUTGOING_MESSAGE_DELIVERY_WITH_ID = 31;
-    private static final int UNIFIED_MESSAGE_ON_THREAD = 32;
-    private static final int UNIFIED_MESSAGE_ON_THREAD_WITH_ID = 33;
-    private static final int INCOMING_MESSAGE_ON_P2P_THREAD = 34;
-    private static final int INCOMING_MESSAGE_ON_P2P_THREAD_WITH_ID = 35;
-    private static final int OUTGOING_MESSAGE_ON_P2P_THREAD = 36;
-    private static final int OUTGOING_MESSAGE_ON_P2P_THREAD_WITH_ID = 37;
-    private static final int INCOMING_MESSAGE_ON_GROUP_THREAD = 38;
-    private static final int INCOMING_MESSAGE_ON_GROUP_THREAD_WITH_ID = 39;
-    private static final int OUTGOING_MESSAGE_ON_GROUP_THREAD = 40;
-    private static final int OUTGOING_MESSAGE_ON_GROUP_THREAD_WITH_ID = 41;
-    private static final int FILE_TRANSFER_WITH_ID = 42;
-    private static final int EVENT = 43;
-    private static final int CANONICAL_ADDRESS = 44;
-
-    SQLiteOpenHelper mDbOpenHelper;
-
-    @VisibleForTesting
-    RcsProviderThreadHelper mThreadHelper;
-    @VisibleForTesting
-    RcsProviderParticipantHelper mParticipantHelper;
-    @VisibleForTesting
-    RcsProviderMessageHelper mMessageHelper;
-    @VisibleForTesting
-    RcsProviderEventHelper mEventHelper;
-    @VisibleForTesting
-    RcsProviderCanonicalAddressHelper mCanonicalAddressHelper;
-
-    static {
-        // example URI: content://rcs/thread
-        URL_MATCHER.addURI(AUTHORITY, RCS_THREAD_URI_PART, UNIFIED_RCS_THREAD);
-
-        // example URI: content://rcs/thread/4, where 4 is the thread id.
-        URL_MATCHER.addURI(AUTHORITY, "thread/#", UNIFIED_RCS_THREAD_WITH_ID);
-
-        // example URI: content://rcs/participant
-        URL_MATCHER.addURI(AUTHORITY, "participant", PARTICIPANT);
-
-        // example URI: content://rcs/participant/12, where 12 is the participant id
-        URL_MATCHER.addURI(AUTHORITY, "participant/#", PARTICIPANT_WITH_ID);
-
-        // example URI: content://rcs/participant/12/alias_change_event, where 12 is the participant
-        // id.
-        URL_MATCHER.addURI(AUTHORITY, "participant/#/alias_change_event",
-                PARTICIPANT_ALIAS_CHANGE_EVENT);
-
-        // example URI: content://rcs/participant/12/alias_change_event/4, where 12 is the
-        // participant id, and 4 is the event id
-        URL_MATCHER.addURI(AUTHORITY, "participant/#/alias_change_event/#",
-                PARTICIPANT_ALIAS_CHANGE_EVENT_WITH_ID);
-
-        // example URI: content://rcs/p2p_thread
-        URL_MATCHER.addURI(AUTHORITY, "p2p_thread", P2P_THREAD);
-
-        // example URI: content://rcs/p2p_thread/4, where 4 is the thread id
-        URL_MATCHER.addURI(AUTHORITY, "p2p_thread/#", P2P_THREAD_WITH_ID);
-
-        // example URI: content://rcs/p2p_thread/4/participant, where 4 is the thread id
-        URL_MATCHER.addURI(AUTHORITY, "p2p_thread/#/participant", P2P_THREAD_PARTICIPANT);
-
-        // example URI: content://rcs/p2p_thread/9/participant/3", only supports a 1 time insert.
-        // 9 is the thread ID, 3 is the participant ID.
-        URL_MATCHER.addURI(AUTHORITY, "p2p_thread/#/participant/#", P2P_THREAD_PARTICIPANT_WITH_ID);
-
-        // example URI: content://rcs/group_thread
-        URL_MATCHER.addURI(AUTHORITY, "group_thread", GROUP_THREAD);
-
-        // example URI: content://rcs/group_thread/13, where 13 is the _id in rcs_threads table.
-        URL_MATCHER.addURI(AUTHORITY, "group_thread/#", GROUP_THREAD_WITH_ID);
-
-        // example URI: content://rcs/group_thread/13/participant_joined_event. Supports
-        // queries and inserts
-        URL_MATCHER.addURI(AUTHORITY, "group_thread/#/participant_joined_event",
-                GROUP_THREAD_PARTICIPANT_JOINED_EVENT);
-
-        // example URI: content://rcs/group_thread/13/participant_joined_event/3. Supports deletes.
-        URL_MATCHER.addURI(AUTHORITY, "group_thread/#/participant_joined_event/#",
-                GROUP_THREAD_PARTICIPANT_JOINED_EVENT_WITH_ID);
-
-        // example URI: content://rcs/group_thread/13/participant_left_event. Supports queries
-        // and inserts
-        URL_MATCHER.addURI(AUTHORITY, "group_thread/#/participant_left_event",
-                GROUP_THREAD_PARTICIPANT_LEFT_EVENT);
-
-        // example URI: content://rcs/group_thread/13/participant_left_event/5. Supports deletes
-        URL_MATCHER.addURI(AUTHORITY, "group_thread/#/participant_left_event/#",
-                GROUP_THREAD_PARTICIPANT_LEFT_EVENT_WITH_ID);
-
-        // example URI: content://rcs/group_thread/13/name_changed_event. Supports queries and
-        // inserts
-        URL_MATCHER.addURI(AUTHORITY, "group_thread/#/name_changed_event",
-                GROUP_THREAD_NAME_CHANGE_EVENT);
-
-        // example URI: content://rcs/group_thread/13/name_changed_event/7. Supports deletes
-        URL_MATCHER.addURI(AUTHORITY, "group_thread/#/name_changed_event/#",
-                GROUP_THREAD_NAME_CHANGE_EVENT_WITH_ID);
-
-        // example URI: content://rcs/group_thread/13/icon_changed_event. Supports queries and
-        // inserts
-        URL_MATCHER.addURI(AUTHORITY, "group_thread/#/icon_changed_event",
-                GROUP_THREAD_ICON_CHANGE_EVENT);
-
-        // example URI: content://rcs/group_thread/13/icon_changed_event/9. Supports deletes
-        URL_MATCHER.addURI(AUTHORITY, "group_thread/#/icon_changed_event/#",
-                GROUP_THREAD_ICON_CHANGE_EVENT_WITH_ID);
-
-        // example URI: content://rcs/group_thread/18/participant
-        URL_MATCHER.addURI(AUTHORITY, "group_thread/#/participant",
-                GROUP_THREAD_PARTICIPANT);
-
-        // example URI: content://rcs/group_thread/21/participant/4, only supports inserts and
-        // deletes
-        URL_MATCHER.addURI(AUTHORITY, "group_thread/#/participant/#",
-                GROUP_THREAD_PARTICIPANT_WITH_ID);
-
-        // example URI: content://rcs/message
-        URL_MATCHER.addURI(AUTHORITY, "message", UNIFIED_MESSAGE);
-
-        // example URI: content://rcs/message/4, where 4 is the message id.
-        URL_MATCHER.addURI(AUTHORITY, "message/#", UNIFIED_MESSAGE_WITH_ID);
-
-        // example URI: content://rcs/message/4/file_transfer, only supports inserts
-        URL_MATCHER.addURI(AUTHORITY, "message/#/file_transfer",
-                UNIFIED_MESSAGE_WITH_FILE_TRANSFER);
-
-        // example URI: content://rcs/incoming_message
-        URL_MATCHER.addURI(AUTHORITY, "incoming_message", INCOMING_MESSAGE);
-
-        // example URI: content://rcs/incoming_message/45
-        URL_MATCHER.addURI(AUTHORITY, "incoming_message/#", INCOMING_MESSAGE_WITH_ID);
-
-        // example URI: content://rcs/outgoing_message
-        URL_MATCHER.addURI(AUTHORITY, "outgoing_message", OUTGOING_MESSAGE);
-
-        // example URI: content://rcs/outgoing_message/54
-        URL_MATCHER.addURI(AUTHORITY, "outgoing_message/#", OUTGOING_MESSAGE_WITH_ID);
-
-        // example URI: content://rcs/outgoing_message/54/delivery. Only supports queries
-        URL_MATCHER.addURI(AUTHORITY, "outgoing_message/#/delivery", OUTGOING_MESSAGE_DELIVERY);
-
-        // example URI: content://rcs/outgoing_message/9/delivery/4. Does not support queries
-        URL_MATCHER.addURI(AUTHORITY, "outgoing_message/#/delivery/#",
-                OUTGOING_MESSAGE_DELIVERY_WITH_ID);
-
-        // example URI: content://rcs/thread/5/message, only supports querying.
-        URL_MATCHER.addURI(AUTHORITY, "thread/#/message", UNIFIED_MESSAGE_ON_THREAD);
-
-        // example URI: content://rcs/thread/5/message/40, only supports querying.
-        URL_MATCHER.addURI(AUTHORITY, "thread/#/message/#", UNIFIED_MESSAGE_ON_THREAD_WITH_ID);
-
-        // example URI: content://rcs/p2p_thread/3/incoming_message. Only available for inserting
-        // incoming messages onto a 1 to 1 thread.
-        URL_MATCHER.addURI(AUTHORITY, "p2p_thread/#/incoming_message",
-                INCOMING_MESSAGE_ON_P2P_THREAD);
-
-        // example URI: content://rcs/p2p_thread/11/incoming_message/45. Only supports querying
-        URL_MATCHER.addURI(AUTHORITY, "p2p_thread/#/incoming_message/#",
-                INCOMING_MESSAGE_ON_P2P_THREAD_WITH_ID);
-
-        // example URI: content://rcs/p2p_thread/3/outgoing_message. Only available for inserting
-        // outgoing messages onto a 1 to 1 thread.
-        URL_MATCHER.addURI(AUTHORITY, "p2p_thread/#/outgoing_message",
-                OUTGOING_MESSAGE_ON_P2P_THREAD);
-
-        // example URI: content://rcs/p2p_thread/11/outgoing_message/46. Only supports querying
-        URL_MATCHER.addURI(AUTHORITY, "p2p_thread/#/outgoing_message/#",
-                OUTGOING_MESSAGE_ON_P2P_THREAD_WITH_ID);
-
-        // example URI: content://rcs/group_thread/3/incoming_message. Only available for inserting
-        // incoming messages onto a group thread.
-        URL_MATCHER.addURI(AUTHORITY, "group_thread/#/incoming_message",
-                INCOMING_MESSAGE_ON_GROUP_THREAD);
-
-        // example URI: content://rcs/group_thread/3/incoming_message/71. Only supports querying
-        URL_MATCHER.addURI(AUTHORITY, "group_thread/#/incoming_message/#",
-                INCOMING_MESSAGE_ON_GROUP_THREAD_WITH_ID);
-
-        // example URI: content://rcs/group_thread/3/outgoing_message. Only available for inserting
-        // outgoing messages onto a group thread.
-        URL_MATCHER.addURI(AUTHORITY, "group_thread/#/outgoing_message",
-                OUTGOING_MESSAGE_ON_GROUP_THREAD);
-
-        // example URI: content://rcs/group_thread/13/outgoing_message/72. Only supports querying
-        URL_MATCHER.addURI(AUTHORITY, "group_thread/#/outgoing_message/#",
-                OUTGOING_MESSAGE_ON_GROUP_THREAD_WITH_ID);
-
-        // example URI: content://rcs/file_transfer/1. Does not support insertion
-        URL_MATCHER.addURI(AUTHORITY, "file_transfer/#", FILE_TRANSFER_WITH_ID);
-
-        // example URI: content://rcs/event
-        URL_MATCHER.addURI(AUTHORITY, "event", EVENT);
-
-        URL_MATCHER.addURI(AUTHORITY, "canonical-address", CANONICAL_ADDRESS);
-    }
-
-    @Override
-    public boolean onCreate() {
-        // Use the credential encrypted mmssms.db for RCS messages.
-        mDbOpenHelper = MmsSmsDatabaseHelper.getInstanceForCe(getContext());
-        mParticipantHelper = new RcsProviderParticipantHelper(mDbOpenHelper);
-        mThreadHelper = new RcsProviderThreadHelper(mDbOpenHelper);
-        mMessageHelper = new RcsProviderMessageHelper(mDbOpenHelper);
-        mEventHelper = new RcsProviderEventHelper(mDbOpenHelper);
-        mCanonicalAddressHelper = new RcsProviderCanonicalAddressHelper(mDbOpenHelper);
-        return true;
-    }
-
-    /**
-     * ContentResolver has a weird bug that if both query methods are overridden, it will always
-     * pick the bundle one to call, but will still require us to override this one as it is
-     * abstract. Work around by putting parameters in a bundle.
-     */
-    @Override
-    public synchronized Cursor query(Uri uri, String[] projection, String selection,
-            String[] selectionArgs, String sortOrder) {
-        Bundle bundle = new Bundle();
-        bundle.putString(ContentResolver.QUERY_ARG_SQL_SELECTION, selection);
-        bundle.putStringArray(ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS, selectionArgs);
-        bundle.putString(ContentResolver.QUERY_ARG_SQL_SORT_ORDER, sortOrder);
-        return query(uri, projection, bundle, null);
-    }
-
-    @Override
-    public synchronized Cursor query(Uri uri, String[] projection, Bundle queryArgs,
-            CancellationSignal unused) {
-        int match = URL_MATCHER.match(uri);
-
-        String selection = null;
-        String[] selectionArgs = null;
-        String sortOrder = null;
-
-        if (queryArgs != null) {
-            selection = queryArgs.getString(ContentResolver.QUERY_ARG_SQL_SELECTION);
-            selectionArgs = queryArgs.getStringArray(
-                    ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS);
-            sortOrder = queryArgs.getString(ContentResolver.QUERY_ARG_SQL_SORT_ORDER);
-        }
-
-        switch (match) {
-            case UNIFIED_RCS_THREAD:
-                return mThreadHelper.queryUnifiedThread(queryArgs);
-            case UNIFIED_RCS_THREAD_WITH_ID:
-                return mThreadHelper.queryUnifiedThreadUsingId(uri, projection);
-            case PARTICIPANT:
-                return mParticipantHelper.queryParticipant(queryArgs);
-            case PARTICIPANT_WITH_ID:
-                return mParticipantHelper.queryParticipantWithId(uri, projection);
-            case PARTICIPANT_ALIAS_CHANGE_EVENT:
-                Log.e(TAG, "Querying individual event types is not supported, uri: " + uri);
-                break;
-            case PARTICIPANT_ALIAS_CHANGE_EVENT_WITH_ID:
-                Log.e(TAG, "Querying participant events with id's is not supported, uri: " + uri);
-                break;
-            case P2P_THREAD:
-                return mThreadHelper.query1to1Thread(projection, selection,
-                        selectionArgs, sortOrder);
-            case P2P_THREAD_WITH_ID:
-                return mThreadHelper.query1To1ThreadUsingId(uri, projection);
-            case P2P_THREAD_PARTICIPANT:
-                return mParticipantHelper.queryParticipantIn1To1Thread(uri);
-            case P2P_THREAD_PARTICIPANT_WITH_ID:
-                Log.e(TAG,
-                        "Querying participants in 1 to 1 threads via id's is not supported, uri: "
-                                + uri);
-                break;
-            case GROUP_THREAD:
-                return mThreadHelper.queryGroupThread(projection, selection,
-                        selectionArgs, sortOrder);
-            case GROUP_THREAD_WITH_ID:
-                return mThreadHelper.queryGroupThreadUsingId(uri, projection);
-            case GROUP_THREAD_PARTICIPANT:
-                return mParticipantHelper.queryParticipantsInGroupThread(uri);
-            case GROUP_THREAD_PARTICIPANT_WITH_ID:
-                return mParticipantHelper.queryParticipantInGroupThreadWithId(uri);
-            case GROUP_THREAD_PARTICIPANT_JOINED_EVENT:
-            case GROUP_THREAD_PARTICIPANT_JOINED_EVENT_WITH_ID:
-            case GROUP_THREAD_PARTICIPANT_LEFT_EVENT:
-            case GROUP_THREAD_PARTICIPANT_LEFT_EVENT_WITH_ID:
-            case GROUP_THREAD_NAME_CHANGE_EVENT:
-            case GROUP_THREAD_NAME_CHANGE_EVENT_WITH_ID:
-            case GROUP_THREAD_ICON_CHANGE_EVENT:
-            case GROUP_THREAD_ICON_CHANGE_EVENT_WITH_ID:
-                Log.e(TAG, "Querying individual event types is not supported, uri: " + uri);
-                break;
-            case UNIFIED_MESSAGE:
-                return mMessageHelper.queryMessages(queryArgs);
-            case UNIFIED_MESSAGE_WITH_ID:
-                return mMessageHelper.queryUnifiedMessageWithId(uri);
-            case UNIFIED_MESSAGE_WITH_FILE_TRANSFER:
-                Log.e(TAG,
-                        "Querying file transfers through messages is not supported, uri: " + uri);
-            case INCOMING_MESSAGE:
-                return mMessageHelper.queryIncomingMessageWithSelection(selection, selectionArgs);
-            case INCOMING_MESSAGE_WITH_ID:
-                return mMessageHelper.queryIncomingMessageWithId(uri);
-            case OUTGOING_MESSAGE:
-                return mMessageHelper.queryOutgoingMessageWithSelection(selection, selectionArgs);
-            case OUTGOING_MESSAGE_WITH_ID:
-                return mMessageHelper.queryOutgoingMessageWithId(uri);
-            case OUTGOING_MESSAGE_DELIVERY:
-                return mMessageHelper.queryOutgoingMessageDeliveries(uri);
-            case OUTGOING_MESSAGE_DELIVERY_WITH_ID:
-                Log.e(TAG,
-                        "Querying deliveries with message and participant ids is not supported, "
-                                + "uri: "
-                                + uri);
-            case UNIFIED_MESSAGE_ON_THREAD:
-                return mMessageHelper.queryAllMessagesOnThread(uri, selection, selectionArgs);
-            case UNIFIED_MESSAGE_ON_THREAD_WITH_ID:
-                return mMessageHelper.queryUnifiedMessageWithIdInThread(uri);
-            case INCOMING_MESSAGE_ON_P2P_THREAD:
-                Log.e(TAG,
-                        "Querying incoming messages on P2P thread with selection is not "
-                                + "supported, uri: "
-                                + uri);
-                break;
-            case INCOMING_MESSAGE_ON_P2P_THREAD_WITH_ID:
-                return mMessageHelper.queryUnifiedMessageWithIdInThread(uri);
-            case OUTGOING_MESSAGE_ON_P2P_THREAD:
-                Log.e(TAG,
-                        "Querying outgoing messages on P2P thread with selection is not "
-                                + "supported, uri: "
-                                + uri);
-                break;
-            case OUTGOING_MESSAGE_ON_P2P_THREAD_WITH_ID:
-                return mMessageHelper.queryUnifiedMessageWithIdInThread(uri);
-            case INCOMING_MESSAGE_ON_GROUP_THREAD:
-                Log.e(TAG,
-                        "Querying incoming messages on group thread with selection is not "
-                                + "supported, uri: "
-                                + uri);
-                break;
-            case INCOMING_MESSAGE_ON_GROUP_THREAD_WITH_ID:
-                return mMessageHelper.queryUnifiedMessageWithIdInThread(uri);
-            case OUTGOING_MESSAGE_ON_GROUP_THREAD:
-                Log.e(TAG,
-                        "Querying outgoing messages on group thread with selection is not "
-                                + "supported, uri: "
-                                + uri);
-                break;
-            case OUTGOING_MESSAGE_ON_GROUP_THREAD_WITH_ID:
-                return mMessageHelper.queryUnifiedMessageWithIdInThread(uri);
-            case FILE_TRANSFER_WITH_ID:
-                return mMessageHelper.queryFileTransfer(uri);
-            case EVENT:
-                return mEventHelper.queryEvents(queryArgs);
-            case CANONICAL_ADDRESS:
-                String canonicalAddress = uri.getQueryParameter("address");
-                return mCanonicalAddressHelper.getOrCreateCanonicalAddress(canonicalAddress);
-            default:
-                Log.e(TAG, "Invalid query: " + uri);
-        }
-
-        return null;
-    }
-
-    @Override
-    public String getType(Uri uri) {
-        return null;
-    }
-
-    @Override
-    public synchronized Uri insert(Uri uri, ContentValues values) {
-        int match = URL_MATCHER.match(uri);
-        long rowId;
-
-        switch (match) {
-            case UNIFIED_RCS_THREAD:
-            case UNIFIED_RCS_THREAD_WITH_ID:
-                Log.e(TAG, "Inserting into unified thread view is not supported, uri: " + uri);
-                break;
-            case PARTICIPANT:
-                return buildUriWithRowIdAppended(PARTICIPANT_URI_PREFIX,
-                        mParticipantHelper.insertParticipant(values));
-            case PARTICIPANT_WITH_ID:
-                Log.e(TAG, "Inserting participant with a specified ID is not supported, uri: "
-                        + uri);
-                break;
-            case PARTICIPANT_ALIAS_CHANGE_EVENT:
-                return buildUriWithRowIdAppended(uri,
-                        mEventHelper.insertParticipantEvent(uri, values));
-            case PARTICIPANT_ALIAS_CHANGE_EVENT_WITH_ID:
-                Log.e(TAG, "Inserting participant events with id's is not supported, uri: " + uri);
-                break;
-            case P2P_THREAD:
-                return buildUriWithRowIdAppended(P2P_THREAD_URI_PREFIX,
-                        mThreadHelper.insert1To1Thread(values));
-            case P2P_THREAD_WITH_ID:
-                Log.e(TAG, "Inserting a thread with a specified ID is not supported, uri: " + uri);
-                break;
-            case P2P_THREAD_PARTICIPANT:
-                Log.e(TAG,
-                        "Inserting a participant into a thread via content values is not "
-                                + "supported, uri: "
-                                + uri);
-                break;
-            case P2P_THREAD_PARTICIPANT_WITH_ID:
-                Log.e(TAG,
-                        "Inserting participant into a thread via URI is not supported, uri: "
-                                + uri);
-                break;
-            case GROUP_THREAD:
-                return buildUriWithRowIdAppended(GROUP_THREAD_URI_PREFIX,
-                        mThreadHelper.insertGroupThread(values));
-            case GROUP_THREAD_WITH_ID:
-                Log.e(TAG, "Inserting a thread with a specified ID is not supported, uri: " + uri);
-                break;
-            case GROUP_THREAD_PARTICIPANT_JOINED_EVENT:
-                return buildUriWithRowIdAppended(uri,
-                        mEventHelper.insertParticipantJoinedEvent(uri, values));
-            case GROUP_THREAD_PARTICIPANT_JOINED_EVENT_WITH_ID:
-                Log.e(TAG, "Inserting thread events with id's is not supported, uri: " + uri);
-                break;
-            case GROUP_THREAD_PARTICIPANT_LEFT_EVENT:
-                return buildUriWithRowIdAppended(uri,
-                        mEventHelper.insertParticipantLeftEvent(uri, values));
-            case GROUP_THREAD_PARTICIPANT_LEFT_EVENT_WITH_ID:
-                Log.e(TAG, "Inserting thread events with id's is not supported, uri: " + uri);
-                break;
-            case GROUP_THREAD_NAME_CHANGE_EVENT:
-                return buildUriWithRowIdAppended(uri,
-                        mEventHelper.insertThreadNameChangeEvent(uri, values));
-            case GROUP_THREAD_NAME_CHANGE_EVENT_WITH_ID:
-                Log.e(TAG, "Inserting thread events with id's is not supported, uri: " + uri);
-                break;
-            case GROUP_THREAD_ICON_CHANGE_EVENT:
-                return buildUriWithRowIdAppended(uri,
-                        mEventHelper.insertThreadIconChangeEvent(uri, values));
-            case GROUP_THREAD_ICON_CHANGE_EVENT_WITH_ID:
-                Log.e(TAG, "Inserting thread events with id's is not supported, uri: " + uri);
-                break;
-            case GROUP_THREAD_PARTICIPANT:
-                rowId = mParticipantHelper.insertParticipantIntoGroupThread(values);
-                if (rowId == TRANSACTION_FAILED) {
-                    return null;
-                }
-                return mParticipantHelper.getParticipantInThreadUri(values, rowId);
-            case GROUP_THREAD_PARTICIPANT_WITH_ID:
-                return returnUriAsIsIfSuccessful(uri,
-                        mParticipantHelper.insertParticipantIntoGroupThreadWithId(uri));
-            case UNIFIED_MESSAGE:
-            case UNIFIED_MESSAGE_WITH_ID:
-                Log.e(TAG, "Inserting into unified message view is not supported, uri: " + uri);
-                break;
-            case UNIFIED_MESSAGE_WITH_FILE_TRANSFER:
-                return buildUriWithRowIdAppended(FILE_TRANSFER_PREFIX,
-                        mMessageHelper.insertFileTransferToMessage(uri, values));
-            case INCOMING_MESSAGE:
-            case INCOMING_MESSAGE_WITH_ID:
-            case OUTGOING_MESSAGE:
-            case OUTGOING_MESSAGE_WITH_ID:
-                Log.e(TAG, "Inserting a message without a thread is not supported, uri: "
-                        + uri);
-                break;
-            case OUTGOING_MESSAGE_DELIVERY:
-                Log.e(TAG,
-                        "Inserting an outgoing message delivery without a participant is not "
-                                + "supported, uri: "
-                                + uri);
-                break;
-            case OUTGOING_MESSAGE_DELIVERY_WITH_ID:
-                return returnUriAsIsIfSuccessful(uri,
-                        mMessageHelper.insertMessageDelivery(uri, values));
-            case UNIFIED_MESSAGE_ON_THREAD:
-            case UNIFIED_MESSAGE_ON_THREAD_WITH_ID:
-                Log.e(TAG,
-                        "Inserting a message on unified thread view is not supported, uri: " + uri);
-                break;
-            case INCOMING_MESSAGE_ON_P2P_THREAD:
-                return mMessageHelper.insertMessageOnThread(uri, values, /* isIncoming= */
-                        true, /* is1To1 */ true);
-            case OUTGOING_MESSAGE_ON_P2P_THREAD:
-                return mMessageHelper.insertMessageOnThread(uri, values, /* isIncoming= */
-                        false, /* is1To1 */ true);
-            case INCOMING_MESSAGE_ON_GROUP_THREAD:
-                return mMessageHelper.insertMessageOnThread(uri, values, /* isIncoming= */
-                        true, /* is1To1 */ false);
-            case OUTGOING_MESSAGE_ON_GROUP_THREAD:
-                return mMessageHelper.insertMessageOnThread(uri, values, /* isIncoming= */
-                        false, /* is1To1 */ false);
-            case INCOMING_MESSAGE_ON_P2P_THREAD_WITH_ID:
-            case OUTGOING_MESSAGE_ON_P2P_THREAD_WITH_ID:
-            case INCOMING_MESSAGE_ON_GROUP_THREAD_WITH_ID:
-            case OUTGOING_MESSAGE_ON_GROUP_THREAD_WITH_ID:
-                Log.e(TAG, "Inserting a message with a specific id is not supported, uri: " + uri);
-                break;
-            case FILE_TRANSFER_WITH_ID:
-                Log.e(TAG, "Inserting a file transfer without a message is not supported, uri: "
-                        + uri);
-                break;
-            case EVENT:
-                Log.e(TAG,
-                        "Inserting event using unified event query is not supported, uri: " + uri);
-                break;
-            default:
-                Log.e(TAG, "Invalid insert: " + uri);
-        }
-
-        return null;
-    }
-
-    @Override
-    public synchronized int delete(Uri uri, String selection, String[] selectionArgs) {
-        int match = URL_MATCHER.match(uri);
-        int deletedCount = 0;
-
-        switch (match) {
-            case UNIFIED_RCS_THREAD:
-            case UNIFIED_RCS_THREAD_WITH_ID:
-                Log.e(TAG, "Deleting entries from unified view is not allowed: " + uri);
-                break;
-            case PARTICIPANT:
-                Log.e(TAG, "Deleting participant with selection is not allowed: " + uri);
-                break;
-            case PARTICIPANT_WITH_ID:
-                return mParticipantHelper.deleteParticipantWithId(uri);
-            case PARTICIPANT_ALIAS_CHANGE_EVENT:
-                Log.e(TAG, "Deleting participant events without id is not allowed: " + uri);
-                break;
-            case PARTICIPANT_ALIAS_CHANGE_EVENT_WITH_ID:
-                return mEventHelper.deleteParticipantEvent(uri);
-            case P2P_THREAD:
-                return mThreadHelper.delete1To1Thread(selection, selectionArgs);
-            case P2P_THREAD_WITH_ID:
-                return mThreadHelper.delete1To1ThreadWithId(uri);
-            case P2P_THREAD_PARTICIPANT:
-                Log.e(TAG, "Removing participant from 1 to 1 thread is not allowed, uri: " + uri);
-                break;
-            case GROUP_THREAD:
-                return mThreadHelper.deleteGroupThread(selection, selectionArgs);
-            case GROUP_THREAD_WITH_ID:
-                return mThreadHelper.deleteGroupThreadWithId(uri);
-            case GROUP_THREAD_PARTICIPANT_JOINED_EVENT_WITH_ID:
-                return mEventHelper.deleteGroupThreadEvent(uri);
-            case GROUP_THREAD_PARTICIPANT_LEFT_EVENT_WITH_ID:
-                return mEventHelper.deleteGroupThreadEvent(uri);
-            case GROUP_THREAD_NAME_CHANGE_EVENT_WITH_ID:
-                return mEventHelper.deleteGroupThreadEvent(uri);
-            case GROUP_THREAD_PARTICIPANT_JOINED_EVENT:
-            case GROUP_THREAD_PARTICIPANT_LEFT_EVENT:
-            case GROUP_THREAD_NAME_CHANGE_EVENT:
-            case GROUP_THREAD_ICON_CHANGE_EVENT:
-                Log.e(TAG, "Deleting thread events via selection is not allowed, uri: " + uri);
-                break;
-            case GROUP_THREAD_ICON_CHANGE_EVENT_WITH_ID:
-                return mEventHelper.deleteGroupThreadEvent(uri);
-            case GROUP_THREAD_PARTICIPANT:
-                Log.e(TAG,
-                        "Deleting a participant from group thread via selection is not allowed, "
-                                + "uri: "
-                                + uri);
-                break;
-            case GROUP_THREAD_PARTICIPANT_WITH_ID:
-                return mParticipantHelper.deleteParticipantFromGroupThread(uri);
-            case UNIFIED_MESSAGE:
-                Log.e(TAG,
-                        "Deleting message from unified view with selection is not allowed: " + uri);
-                break;
-            case UNIFIED_MESSAGE_WITH_ID:
-                Log.e(TAG, "Deleting message from unified view with id is not allowed: " + uri);
-                break;
-            case UNIFIED_MESSAGE_WITH_FILE_TRANSFER:
-                Log.e(TAG, "Deleting file transfer using message uri is not allowed, uri: " + uri);
-                break;
-            case INCOMING_MESSAGE:
-                return mMessageHelper.deleteIncomingMessageWithSelection(selection, selectionArgs);
-            case INCOMING_MESSAGE_WITH_ID:
-                return mMessageHelper.deleteIncomingMessageWithId(uri);
-            case OUTGOING_MESSAGE:
-                return mMessageHelper.deleteOutgoingMessageWithSelection(selection, selectionArgs);
-            case OUTGOING_MESSAGE_WITH_ID:
-                return mMessageHelper.deleteOutgoingMessageWithId(uri);
-            case OUTGOING_MESSAGE_DELIVERY:
-            case OUTGOING_MESSAGE_DELIVERY_WITH_ID:
-                Log.e(TAG, "Deleting message deliveries is not supported, uri: " + uri);
-                break;
-            case UNIFIED_MESSAGE_ON_THREAD:
-            case UNIFIED_MESSAGE_ON_THREAD_WITH_ID:
-            case INCOMING_MESSAGE_ON_P2P_THREAD:
-            case INCOMING_MESSAGE_ON_P2P_THREAD_WITH_ID:
-            case OUTGOING_MESSAGE_ON_P2P_THREAD:
-            case OUTGOING_MESSAGE_ON_P2P_THREAD_WITH_ID:
-            case INCOMING_MESSAGE_ON_GROUP_THREAD:
-            case INCOMING_MESSAGE_ON_GROUP_THREAD_WITH_ID:
-            case OUTGOING_MESSAGE_ON_GROUP_THREAD:
-            case OUTGOING_MESSAGE_ON_GROUP_THREAD_WITH_ID:
-                Log.e(TAG, "Deleting messages using thread uris is not supported, uri: " + uri);
-                break;
-            case FILE_TRANSFER_WITH_ID:
-                return mMessageHelper.deleteFileTransfer(uri);
-            case EVENT:
-                Log.e(TAG, "Deleting events using unified event uri is not supported, uri: " + uri);
-                break;
-            default:
-                Log.e(TAG, "Invalid delete: " + uri);
-        }
-
-        return deletedCount;
-    }
-
-    @Override
-    public synchronized int update(Uri uri, ContentValues values, String selection,
-            String[] selectionArgs) {
-        int match = URL_MATCHER.match(uri);
-        int updatedCount = 0;
-
-        switch (match) {
-            case UNIFIED_RCS_THREAD:
-            case UNIFIED_RCS_THREAD_WITH_ID:
-                Log.e(TAG, "Updating unified thread view is not supported, uri: " + uri);
-                break;
-            case PARTICIPANT:
-                Log.e(TAG, "Updating participants with selection is not supported, uri: " + uri);
-                break;
-            case PARTICIPANT_WITH_ID:
-                return mParticipantHelper.updateParticipantWithId(values, uri);
-            case PARTICIPANT_ALIAS_CHANGE_EVENT:
-            case PARTICIPANT_ALIAS_CHANGE_EVENT_WITH_ID:
-                Log.e(TAG, "Updating events is not supported, uri: " + uri);
-                break;
-            case P2P_THREAD:
-                return mThreadHelper.update1To1Thread(values, selection, selectionArgs);
-            case P2P_THREAD_WITH_ID:
-                return mThreadHelper.update1To1ThreadWithId(values, uri);
-            case P2P_THREAD_PARTICIPANT:
-                Log.e(TAG, "Updating junction table entries is not supported, uri: " + uri);
-                break;
-            case GROUP_THREAD:
-                return mThreadHelper.updateGroupThread(values, selection, selectionArgs);
-            case GROUP_THREAD_WITH_ID:
-                return mThreadHelper.updateGroupThreadWithId(values, uri);
-            case GROUP_THREAD_PARTICIPANT_JOINED_EVENT:
-            case GROUP_THREAD_PARTICIPANT_JOINED_EVENT_WITH_ID:
-            case GROUP_THREAD_PARTICIPANT_LEFT_EVENT:
-            case GROUP_THREAD_PARTICIPANT_LEFT_EVENT_WITH_ID:
-            case GROUP_THREAD_NAME_CHANGE_EVENT:
-            case GROUP_THREAD_NAME_CHANGE_EVENT_WITH_ID:
-            case GROUP_THREAD_ICON_CHANGE_EVENT:
-            case GROUP_THREAD_ICON_CHANGE_EVENT_WITH_ID:
-                Log.e(TAG, "Updating thread events is not supported, uri: " + uri);
-                break;
-            case GROUP_THREAD_PARTICIPANT:
-            case GROUP_THREAD_PARTICIPANT_WITH_ID:
-                Log.e(TAG, "Updating junction table entries is not supported, uri: " + uri);
-                break;
-            case UNIFIED_MESSAGE:
-            case UNIFIED_MESSAGE_WITH_ID:
-                Log.e(TAG, "Updating unified message view is not supported, uri: " + uri);
-                break;
-            case UNIFIED_MESSAGE_WITH_FILE_TRANSFER:
-                Log.e(TAG,
-                        "Updating file transfer using unified message uri is not supported, uri: "
-                                + uri);
-            case INCOMING_MESSAGE:
-                Log.e(TAG,
-                        "Updating an incoming message via selection is not supported, uri: " + uri);
-                break;
-            case INCOMING_MESSAGE_WITH_ID:
-                return mMessageHelper.updateIncomingMessage(uri, values);
-            case OUTGOING_MESSAGE:
-                Log.e(TAG,
-                        "Updating an outgoing message via selection is not supported, uri: " + uri);
-                break;
-            case OUTGOING_MESSAGE_WITH_ID:
-                return mMessageHelper.updateOutgoingMessage(uri, values);
-            case OUTGOING_MESSAGE_DELIVERY:
-                Log.e(TAG, "Updating message deliveries using message uris is not supported, uri: "
-                        + uri);
-                break;
-            case OUTGOING_MESSAGE_DELIVERY_WITH_ID:
-                return mMessageHelper.updateDelivery(uri, values);
-            case UNIFIED_MESSAGE_ON_THREAD:
-            case UNIFIED_MESSAGE_ON_THREAD_WITH_ID:
-            case INCOMING_MESSAGE_ON_P2P_THREAD:
-            case INCOMING_MESSAGE_ON_P2P_THREAD_WITH_ID:
-            case OUTGOING_MESSAGE_ON_P2P_THREAD:
-            case OUTGOING_MESSAGE_ON_P2P_THREAD_WITH_ID:
-            case INCOMING_MESSAGE_ON_GROUP_THREAD:
-            case INCOMING_MESSAGE_ON_GROUP_THREAD_WITH_ID:
-            case OUTGOING_MESSAGE_ON_GROUP_THREAD:
-            case OUTGOING_MESSAGE_ON_GROUP_THREAD_WITH_ID:
-                Log.e(TAG, "Updating messages using threads uris is not supported, uri: " + uri);
-                break;
-            case FILE_TRANSFER_WITH_ID:
-                return mMessageHelper.updateFileTransfer(uri, values);
-            case EVENT:
-                Log.e(TAG, "Updating events is not supported, uri: " + uri);
-                break;
-            default:
-                Log.e(TAG, "Invalid update: " + uri);
-        }
-
-        return updatedCount;
-    }
-}
diff --git a/src/com/android/providers/telephony/RcsProviderCanonicalAddressHelper.java b/src/com/android/providers/telephony/RcsProviderCanonicalAddressHelper.java
deleted file mode 100644
index 496b512..0000000
--- a/src/com/android/providers/telephony/RcsProviderCanonicalAddressHelper.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.android.providers.telephony;
-
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.database.MatrixCursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.provider.BaseColumns;
-import android.provider.Telephony;
-
-public class RcsProviderCanonicalAddressHelper {
-    SQLiteOpenHelper mSQLiteOpenHelper;
-
-    RcsProviderCanonicalAddressHelper(SQLiteOpenHelper sqLiteOpenHelper) {
-        mSQLiteOpenHelper = sqLiteOpenHelper;
-    }
-
-    Cursor getOrCreateCanonicalAddress(String canonicalAddress) {
-        SQLiteDatabase db = mSQLiteOpenHelper.getReadableDatabase();
-
-        Cursor cursor = db.query(
-                MmsSmsProvider.TABLE_CANONICAL_ADDRESSES,
-                new String[]{BaseColumns._ID}, Telephony.CanonicalAddressesColumns.ADDRESS + "=?",
-                new String[]{canonicalAddress}, null, null, null);
-
-        if (cursor != null && cursor.getCount() > 0) {
-            return cursor;
-        }
-
-        if (cursor != null) {
-            cursor.close();
-        }
-
-        return insertCanonicalAddress(canonicalAddress);
-    }
-
-    private Cursor insertCanonicalAddress(String canonicalAddress) {
-        ContentValues contentValues = new ContentValues();
-        contentValues.put(Telephony.CanonicalAddressesColumns.ADDRESS, canonicalAddress);
-
-        SQLiteDatabase db = mSQLiteOpenHelper.getWritableDatabase();
-
-        long id = db.insert(MmsSmsProvider.TABLE_CANONICAL_ADDRESSES, null, contentValues);
-
-        if (id == -1) {
-            return null;
-        }
-
-        MatrixCursor matrixCursor = new MatrixCursor(new String[]{BaseColumns._ID}, 1);
-        matrixCursor.addRow(new Object[]{id});
-
-        return matrixCursor;
-    }
-}
diff --git a/src/com/android/providers/telephony/RcsProviderEventHelper.java b/src/com/android/providers/telephony/RcsProviderEventHelper.java
deleted file mode 100644
index c6a6fc6..0000000
--- a/src/com/android/providers/telephony/RcsProviderEventHelper.java
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Copyright (C) 2019 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 static android.provider.Telephony.RcsColumns.RcsEventTypes.PARTICIPANT_ALIAS_CHANGED_EVENT_TYPE;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.RCS_PARTICIPANT_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantEventColumns.NEW_ALIAS_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsEventTypes.ICON_CHANGED_EVENT_TYPE;
-import static android.provider.Telephony.RcsColumns.RcsEventTypes.NAME_CHANGED_EVENT_TYPE;
-import static android.provider.Telephony.RcsColumns.RcsEventTypes.PARTICIPANT_JOINED_EVENT_TYPE;
-import static android.provider.Telephony.RcsColumns.RcsEventTypes.PARTICIPANT_LEFT_EVENT_TYPE;
-import static android.provider.Telephony.RcsColumns.RcsThreadColumns.RCS_THREAD_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.DESTINATION_PARTICIPANT_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.EVENT_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.EVENT_TYPE_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.NEW_ICON_URI_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.NEW_NAME_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.SOURCE_PARTICIPANT_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.TIMESTAMP_COLUMN;
-import static android.provider.Telephony.RcsColumns.TRANSACTION_FAILED;
-import static android.telephony.ims.RcsEventQueryParams.ALL_EVENTS;
-import static android.telephony.ims.RcsEventQueryParams.ALL_GROUP_THREAD_EVENTS;
-import static android.telephony.ims.RcsEventQueryParams.EVENT_QUERY_PARAMETERS_KEY;
-
-import static android.telephony.ims.RcsQueryContinuationToken.EVENT_QUERY_CONTINUATION_TOKEN_TYPE;
-import static android.telephony.ims.RcsQueryContinuationToken.QUERY_CONTINUATION_TOKEN;
-import static com.android.providers.telephony.RcsProvider.RCS_PARTICIPANT_EVENT_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_PARTICIPANT_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_THREAD_EVENT_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_THREAD_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_UNIFIED_EVENT_VIEW;
-import static com.android.providers.telephony.RcsProvider.TAG;
-import static com.android.providers.telephony.RcsProviderThreadHelper.getThreadIdFromUri;
-import static com.android.providers.telephony.RcsProviderUtil.INSERTION_FAILED;
-
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.net.Uri;
-import android.os.Bundle;
-import android.telephony.ims.RcsEventQueryParams;
-import android.telephony.ims.RcsQueryContinuationToken;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-/**
- * Constants and helpers related to events for {@link RcsProvider} to keep the code clean.
- *
- * @hide
- */
-class RcsProviderEventHelper {
-    private static final int PARTICIPANT_INDEX_IN_EVENT_URI = 1;
-    private static final int EVENT_INDEX_IN_EVENT_URI = 3;
-
-    @VisibleForTesting
-    public static void createRcsEventTables(SQLiteDatabase db) {
-        Log.d(TAG, "Creating event tables");
-
-        // Add the event tables
-        db.execSQL("CREATE TABLE " + RCS_THREAD_EVENT_TABLE + "(" + EVENT_ID_COLUMN
-                + " INTEGER PRIMARY KEY AUTOINCREMENT, " + RCS_THREAD_ID_COLUMN + " INTEGER, "
-                + SOURCE_PARTICIPANT_ID_COLUMN + " INTEGER, " + EVENT_TYPE_COLUMN + " INTEGER, "
-                + TIMESTAMP_COLUMN + " INTEGER, " + DESTINATION_PARTICIPANT_ID_COLUMN + " INTEGER, "
-                + NEW_ICON_URI_COLUMN + " TEXT, " + NEW_NAME_COLUMN + " TEXT, " + " FOREIGN KEY ("
-                + RCS_THREAD_ID_COLUMN + ") REFERENCES " + RCS_THREAD_TABLE + " ("
-                + RCS_THREAD_ID_COLUMN + "), FOREIGN KEY (" + SOURCE_PARTICIPANT_ID_COLUMN
-                + ") REFERENCES " + RCS_PARTICIPANT_TABLE + " (" + RCS_PARTICIPANT_ID_COLUMN
-                + "))");
-
-        db.execSQL("CREATE TABLE " + RCS_PARTICIPANT_EVENT_TABLE + "(" + EVENT_ID_COLUMN
-                + " INTEGER PRIMARY KEY AUTOINCREMENT, " + SOURCE_PARTICIPANT_ID_COLUMN +
-                " INTEGER, " + TIMESTAMP_COLUMN + " INTEGER, "
-                + NEW_ALIAS_COLUMN + " TEXT," + " FOREIGN KEY (" + SOURCE_PARTICIPANT_ID_COLUMN
-                + ") REFERENCES " + RCS_PARTICIPANT_TABLE + " (" + RCS_PARTICIPANT_ID_COLUMN
-                + "))");
-
-        // Add the views
-
-        // The following is a unified event view that puts every entry in both tables into one query
-        db.execSQL("CREATE VIEW " + RCS_UNIFIED_EVENT_VIEW + " AS "
-                + "SELECT " + PARTICIPANT_ALIAS_CHANGED_EVENT_TYPE + " AS " + EVENT_TYPE_COLUMN
-                + ", " + EVENT_ID_COLUMN + ", " + SOURCE_PARTICIPANT_ID_COLUMN + ", "
-                + TIMESTAMP_COLUMN + ", " + NEW_ALIAS_COLUMN + ", NULL as " + RCS_THREAD_ID_COLUMN
-                + ", NULL as " + DESTINATION_PARTICIPANT_ID_COLUMN + ", NULL as "
-                + NEW_ICON_URI_COLUMN + ", NULL as " + NEW_NAME_COLUMN + " "
-                + "FROM " + RCS_PARTICIPANT_EVENT_TABLE + " "
-                + "UNION "
-                + "SELECT " + EVENT_TYPE_COLUMN + ", " + EVENT_ID_COLUMN + ", "
-                + SOURCE_PARTICIPANT_ID_COLUMN + ", " + TIMESTAMP_COLUMN + ", "
-                + "NULL as " + NEW_ALIAS_COLUMN + ", " + RCS_THREAD_ID_COLUMN + ", "
-                + DESTINATION_PARTICIPANT_ID_COLUMN + ", " + NEW_ICON_URI_COLUMN + ", "
-                + NEW_NAME_COLUMN + " "
-                + "FROM " + RCS_THREAD_EVENT_TABLE);
-    }
-
-    private final SQLiteOpenHelper mSqLiteOpenHelper;
-
-    Cursor queryEvents(Bundle bundle) {
-        RcsEventQueryParams queryParameters = null;
-        RcsQueryContinuationToken continuationToken = null;
-
-        if (bundle != null) {
-            queryParameters = bundle.getParcelable(EVENT_QUERY_PARAMETERS_KEY);
-            continuationToken = bundle.getParcelable(QUERY_CONTINUATION_TOKEN);
-        }
-
-        if (continuationToken != null) {
-            return RcsProviderUtil.performContinuationQuery(mSqLiteOpenHelper.getReadableDatabase(),
-                    continuationToken);
-        }
-
-        // if no query parameters were entered, build an empty query parameters object
-        if (queryParameters == null) {
-            queryParameters = new RcsEventQueryParams.Builder().build();
-        }
-
-        return performInitialQuery(queryParameters);
-    }
-
-    private Cursor performInitialQuery(RcsEventQueryParams queryParameters) {
-        SQLiteDatabase db = mSqLiteOpenHelper.getReadableDatabase();
-        StringBuilder rawQuery = new StringBuilder("SELECT * FROM ").append(RCS_UNIFIED_EVENT_VIEW);
-
-        int eventType = queryParameters.getEventType();
-        if (eventType != ALL_EVENTS) {
-            rawQuery.append(" WHERE ").append(EVENT_TYPE_COLUMN);
-            if (eventType == ALL_GROUP_THREAD_EVENTS) {
-                rawQuery.append(" IN (").append(
-                        PARTICIPANT_JOINED_EVENT_TYPE).append(", ").append(
-                        PARTICIPANT_LEFT_EVENT_TYPE).append(", ").append(
-                        ICON_CHANGED_EVENT_TYPE).append(", ").append(
-                        NAME_CHANGED_EVENT_TYPE).append(
-                        ")");
-            } else {
-                rawQuery.append("=").append(eventType);
-            }
-        }
-
-        rawQuery.append(" ORDER BY ");
-
-        int sortingProperty = queryParameters.getSortingProperty();
-        if (sortingProperty == RcsEventQueryParams.SORT_BY_TIMESTAMP) {
-            rawQuery.append(TIMESTAMP_COLUMN);
-        } else {
-            rawQuery.append(EVENT_ID_COLUMN);
-        }
-
-        rawQuery.append(queryParameters.getSortDirection() ? " ASC " : " DESC ");
-
-        RcsProviderUtil.appendLimit(rawQuery, queryParameters.getLimit());
-        String rawQueryAsString = rawQuery.toString();
-        Cursor cursor = db.rawQuery(rawQueryAsString, null);
-
-        // if the query was paginated, build the next query
-        int limit = queryParameters.getLimit();
-        if (limit > 0) {
-            RcsProviderUtil.createContinuationTokenBundle(cursor,
-                    new RcsQueryContinuationToken(EVENT_QUERY_CONTINUATION_TOKEN_TYPE,
-                        rawQueryAsString, limit, limit), QUERY_CONTINUATION_TOKEN);
-        }
-
-        return cursor;
-    }
-
-    RcsProviderEventHelper(SQLiteOpenHelper sqLiteOpenHelper) {
-        mSqLiteOpenHelper = sqLiteOpenHelper;
-    }
-
-    long insertParticipantEvent(Uri uri, ContentValues values) {
-        String participantId = getParticipantIdFromUri(uri);
-
-        SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-        values.put(SOURCE_PARTICIPANT_ID_COLUMN, participantId);
-        long rowId = db.insert(RCS_PARTICIPANT_EVENT_TABLE, SOURCE_PARTICIPANT_ID_COLUMN, values);
-        values.remove(SOURCE_PARTICIPANT_ID_COLUMN);
-
-        if (rowId == INSERTION_FAILED) {
-            return TRANSACTION_FAILED;
-        }
-
-        return rowId;
-    }
-
-    long insertParticipantJoinedEvent(Uri uri, ContentValues values) {
-        return insertGroupThreadEvent(uri, values, PARTICIPANT_JOINED_EVENT_TYPE);
-    }
-
-    long insertParticipantLeftEvent(Uri uri, ContentValues values) {
-        return insertGroupThreadEvent(uri, values, PARTICIPANT_LEFT_EVENT_TYPE);
-    }
-
-    long insertThreadNameChangeEvent(Uri uri, ContentValues values) {
-        return insertGroupThreadEvent(uri, values, NAME_CHANGED_EVENT_TYPE);
-    }
-
-    long insertThreadIconChangeEvent(Uri uri, ContentValues values) {
-        return insertGroupThreadEvent(uri, values, ICON_CHANGED_EVENT_TYPE);
-    }
-
-    private long insertGroupThreadEvent(Uri uri, ContentValues valuesParameter,
-            int eventType) {
-        String threadId = getThreadIdFromUri(uri);
-
-        SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-        ContentValues values = new ContentValues(valuesParameter);
-        values.put(EVENT_TYPE_COLUMN, eventType);
-        values.put(RCS_THREAD_ID_COLUMN, threadId);
-        long rowId = db.insert(RCS_THREAD_EVENT_TABLE, EVENT_ID_COLUMN, values);
-
-        if (rowId == INSERTION_FAILED) {
-            return TRANSACTION_FAILED;
-        }
-
-        return rowId;
-    }
-
-    int deleteParticipantEvent(Uri uri) {
-        String eventId = getEventIdFromEventUri(uri);
-        SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-
-        return db.delete(RCS_PARTICIPANT_EVENT_TABLE, EVENT_ID_COLUMN + "=?",
-                new String[]{eventId});
-    }
-
-    int deleteGroupThreadEvent(Uri uri) {
-        String eventId = getEventIdFromEventUri(uri);
-        SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-
-        return db.delete(RCS_THREAD_EVENT_TABLE, EVENT_ID_COLUMN + "=?", new String[]{eventId});
-    }
-
-    private String getEventIdFromEventUri(Uri uri) {
-        return uri.getPathSegments().get(EVENT_INDEX_IN_EVENT_URI);
-    }
-
-    private String getParticipantIdFromUri(Uri uri) {
-        return uri.getPathSegments().get(PARTICIPANT_INDEX_IN_EVENT_URI);
-    }
-}
diff --git a/src/com/android/providers/telephony/RcsProviderMessageHelper.java b/src/com/android/providers/telephony/RcsProviderMessageHelper.java
deleted file mode 100644
index 670c641..0000000
--- a/src/com/android/providers/telephony/RcsProviderMessageHelper.java
+++ /dev/null
@@ -1,707 +0,0 @@
-/*
- * 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 static android.provider.Telephony.RcsColumns.CONTENT_AND_AUTHORITY;
-import static android.provider.Telephony.RcsColumns.Rcs1To1ThreadColumns.RCS_1_TO_1_THREAD_URI_PART;
-import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.CONTENT_TYPE_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.CONTENT_URI_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.FILE_SIZE_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.FILE_TRANSFER_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.HEIGHT_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.DURATION_MILLIS_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.PREVIEW_TYPE_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.PREVIEW_URI_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.SESSION_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.SUCCESSFULLY_TRANSFERRED_BYTES;
-import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.TRANSFER_STATUS_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.WIDTH_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsGroupThreadColumns.RCS_GROUP_THREAD_URI_PART;
-import static android.provider.Telephony.RcsColumns.RcsIncomingMessageColumns.ARRIVAL_TIMESTAMP_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsIncomingMessageColumns.INCOMING_MESSAGE_URI_PART;
-import static android.provider.Telephony.RcsColumns.RcsIncomingMessageColumns.SENDER_PARTICIPANT_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.GLOBAL_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.LATITUDE_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.LONGITUDE_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.MESSAGE_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.MESSAGE_TEXT_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.ORIGINATION_TIMESTAMP_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.STATUS_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.SUB_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageDeliveryColumns.DELIVERED_TIMESTAMP_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsOutgoingMessageColumns.OUTGOING_MESSAGE_URI_PART;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.RCS_PARTICIPANT_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsThreadColumns.RCS_THREAD_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsUnifiedMessageColumns.MESSAGE_TYPE_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsUnifiedMessageColumns.MESSAGE_TYPE_INCOMING;
-import static android.provider.Telephony.RcsColumns.RcsUnifiedMessageColumns.MESSAGE_TYPE_OUTGOING;
-import static android.provider.Telephony.RcsColumns.RcsUnifiedMessageColumns.UNIFIED_INCOMING_MESSAGE_VIEW;
-import static android.provider.Telephony.RcsColumns.RcsUnifiedMessageColumns.UNIFIED_OUTGOING_MESSAGE_VIEW;
-import static android.provider.Telephony.RcsColumns.TRANSACTION_FAILED;
-import static android.telephony.ims.RcsMessageQueryParams.MESSAGE_QUERY_PARAMETERS_KEY;
-import static android.telephony.ims.RcsMessageQueryParams.THREAD_ID_NOT_SET;
-
-import static android.telephony.ims.RcsQueryContinuationToken.MESSAGE_QUERY_CONTINUATION_TOKEN_TYPE;
-import static android.telephony.ims.RcsQueryContinuationToken.QUERY_CONTINUATION_TOKEN;
-import static com.android.providers.telephony.RcsProvider.RCS_FILE_TRANSFER_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_INCOMING_MESSAGE_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_MESSAGE_DELIVERY_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_MESSAGE_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_OUTGOING_MESSAGE_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_PARTICIPANT_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_PARTICIPANT_THREAD_JUNCTION_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_THREAD_TABLE;
-import static com.android.providers.telephony.RcsProvider.TAG;
-import static com.android.providers.telephony.RcsProvider.UNIFIED_MESSAGE_VIEW;
-import static com.android.providers.telephony.RcsProviderThreadHelper.getThreadIdFromUri;
-import static com.android.providers.telephony.RcsProviderUtil.INSERTION_FAILED;
-
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.net.Uri;
-import android.os.Bundle;
-import android.provider.Telephony.RcsColumns.RcsIncomingMessageColumns;
-import android.provider.Telephony.RcsColumns.RcsMessageDeliveryColumns;
-import android.telephony.ims.RcsMessageQueryParams;
-import android.telephony.ims.RcsQueryContinuationToken;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-/**
- * Constants and helpers related to messages for {@link RcsProvider} to keep the code clean.
- *
- * @hide
- */
-public class RcsProviderMessageHelper {
-    private static final int MESSAGE_ID_INDEX_IN_URI = 1;
-    private static final int MESSAGE_ID_INDEX_IN_THREAD_URI = 3;
-
-    private final SQLiteOpenHelper mSqLiteOpenHelper;
-
-    @VisibleForTesting
-    public static void createRcsMessageTables(SQLiteDatabase db) {
-        Log.d(TAG, "Creating message tables");
-
-        // Add the message tables
-        db.execSQL("CREATE TABLE " + RCS_MESSAGE_TABLE + "(" + MESSAGE_ID_COLUMN
-                + " INTEGER PRIMARY KEY AUTOINCREMENT, " + RCS_THREAD_ID_COLUMN + " INTEGER, "
-                + GLOBAL_ID_COLUMN + " TEXT, " + SUB_ID_COLUMN + " INTEGER, " + MESSAGE_TEXT_COLUMN
-                + " TEXT," + LATITUDE_COLUMN + " REAL, " + LONGITUDE_COLUMN + " REAL, "
-                + STATUS_COLUMN + " INTEGER, " + ORIGINATION_TIMESTAMP_COLUMN
-                + " INTEGER, FOREIGN KEY(" + RCS_THREAD_ID_COLUMN + ") REFERENCES "
-                + RCS_THREAD_TABLE + "(" + RCS_THREAD_ID_COLUMN + "))");
-
-        db.execSQL("CREATE TABLE " + RCS_INCOMING_MESSAGE_TABLE + "(" + MESSAGE_ID_COLUMN
-                + " INTEGER PRIMARY KEY, " + SENDER_PARTICIPANT_ID_COLUMN + " INTEGER, "
-                + ARRIVAL_TIMESTAMP_COLUMN + " INTEGER, "
-                + RcsIncomingMessageColumns.SEEN_TIMESTAMP_COLUMN + " INTEGER, FOREIGN KEY ("
-                + MESSAGE_ID_COLUMN + ") REFERENCES " + RCS_MESSAGE_TABLE + "(" + MESSAGE_ID_COLUMN
-                + "))");
-
-        db.execSQL("CREATE TABLE " + RCS_OUTGOING_MESSAGE_TABLE + "(" + MESSAGE_ID_COLUMN
-                + " INTEGER PRIMARY KEY, FOREIGN KEY (" + MESSAGE_ID_COLUMN + ") REFERENCES "
-                + RCS_MESSAGE_TABLE + "(" + MESSAGE_ID_COLUMN + "))");
-
-        db.execSQL("CREATE TABLE " + RCS_MESSAGE_DELIVERY_TABLE + "(" + MESSAGE_ID_COLUMN
-                + " INTEGER, " + RCS_PARTICIPANT_ID_COLUMN + " INTEGER, "
-                + DELIVERED_TIMESTAMP_COLUMN + " INTEGER, "
-                + RcsMessageDeliveryColumns.SEEN_TIMESTAMP_COLUMN + " INTEGER, "
-                + "CONSTRAINT message_delivery PRIMARY KEY (" + MESSAGE_ID_COLUMN + ", "
-                + RCS_PARTICIPANT_ID_COLUMN + "), FOREIGN KEY (" + MESSAGE_ID_COLUMN
-                + ") REFERENCES " + RCS_MESSAGE_TABLE + "(" + MESSAGE_ID_COLUMN + "), FOREIGN KEY ("
-                + RCS_PARTICIPANT_ID_COLUMN + ") REFERENCES " + RCS_PARTICIPANT_TABLE + "("
-                + RCS_PARTICIPANT_ID_COLUMN + "))");
-
-        db.execSQL("CREATE TABLE " + RCS_FILE_TRANSFER_TABLE + " (" + FILE_TRANSFER_ID_COLUMN
-                + " INTEGER PRIMARY KEY AUTOINCREMENT, " + MESSAGE_ID_COLUMN + " INTEGER, "
-                + SESSION_ID_COLUMN + " TEXT, " + CONTENT_URI_COLUMN + " TEXT, "
-                + CONTENT_TYPE_COLUMN + " TEXT, " + FILE_SIZE_COLUMN + " INTEGER, "
-                + SUCCESSFULLY_TRANSFERRED_BYTES + " INTEGER, " + TRANSFER_STATUS_COLUMN +
-                " INTEGER, " + WIDTH_COLUMN + " INTEGER, " + HEIGHT_COLUMN + " INTEGER, "
-                + DURATION_MILLIS_COLUMN + " INTEGER, " + PREVIEW_URI_COLUMN + " TEXT, "
-                + PREVIEW_TYPE_COLUMN + " TEXT, FOREIGN KEY (" + MESSAGE_ID_COLUMN + ") REFERENCES "
-                + RCS_MESSAGE_TABLE + "(" + MESSAGE_ID_COLUMN + "))");
-
-        // Add the views
-        //
-        // The following view inner joins incoming messages with all messages, inner joins outgoing
-        // messages with all messages, and unions them together, while also adding an is_incoming
-        // column for easily telling where the record came from. This may have been achieved with
-        // an outer join but SQLite doesn't support them.
-        //
-        // CREATE VIEW unified_message_view AS
-        //
-        // SELECT rcs_message.rcs_message_row_id,
-        //        rcs_message.rcs_thread_id,
-        //        rcs_message.rcs_message_global_id,
-        //        rcs_message.sub_id,
-        //        rcs_message.status,
-        //        rcs_message.origination_timestamp,
-        //        rcs_message.rcs_text,
-        //        rcs_message.latitude,
-        //        rcs_message.longitude,
-        //        0 AS sender_participant,
-        //        0 AS arrival_timestamp,
-        //        0 AS seen_timestamp,
-        //        outgoing AS message_type
-        //
-        // FROM rcs_message INNER JOIN rcs_outgoing_message
-        //          ON rcs_message.rcs_message_row_id=rcs_outgoing_message.rcs_message_row_id
-        //
-        // UNION
-        //
-        // SELECT rcs_message.rcs_message_row_id,
-        //        rcs_message.rcs_thread_id,
-        //        rcs_message.rcs_message_global_id,
-        //        rcs_message.sub_id,
-        //        rcs_message.status,
-        //        rcs_message.origination_timestamp,
-        //        rcs_message.rcs_text,
-        //        rcs_message.latitude,
-        //        rcs_message.longitude,
-        //        rcs_incoming_message.sender_participant,
-        //        rcs_incoming_message.arrival_timestamp,
-        //        rcs_incoming_message.seen_timestamp,
-        //        incoming AS message_type
-        //
-        // FROM rcs_message INNER JOIN rcs_incoming_message
-        //          ON rcs_message.rcs_message_row_id=rcs_incoming_message.rcs_message_row_id
-        //
-        db.execSQL("CREATE VIEW " + UNIFIED_MESSAGE_VIEW + " AS SELECT "
-                + RCS_MESSAGE_TABLE + "." + MESSAGE_ID_COLUMN + ", "
-                + RCS_MESSAGE_TABLE + "." + RCS_THREAD_ID_COLUMN + ", "
-                + RCS_MESSAGE_TABLE + "." + GLOBAL_ID_COLUMN + ", "
-                + RCS_MESSAGE_TABLE + "." + SUB_ID_COLUMN + ", "
-                + RCS_MESSAGE_TABLE + "." + STATUS_COLUMN + ", "
-                + RCS_MESSAGE_TABLE + "." + ORIGINATION_TIMESTAMP_COLUMN + ", "
-                + RCS_MESSAGE_TABLE + "." + MESSAGE_TEXT_COLUMN + ", "
-                + RCS_MESSAGE_TABLE + "." + LATITUDE_COLUMN + ", "
-                + RCS_MESSAGE_TABLE + "." + LONGITUDE_COLUMN + ", "
-                + "0 AS " + SENDER_PARTICIPANT_ID_COLUMN + ", "
-                + "0 AS " + ARRIVAL_TIMESTAMP_COLUMN + ", "
-                + "0 AS " + RcsIncomingMessageColumns.SEEN_TIMESTAMP_COLUMN + ", "
-                + MESSAGE_TYPE_OUTGOING + " AS " + MESSAGE_TYPE_COLUMN
-                + " FROM " + RCS_MESSAGE_TABLE + " INNER JOIN " + RCS_OUTGOING_MESSAGE_TABLE
-                + " ON " + RCS_MESSAGE_TABLE + "." + MESSAGE_ID_COLUMN + "="
-                + RCS_OUTGOING_MESSAGE_TABLE + "." + MESSAGE_ID_COLUMN
-                + " UNION SELECT "
-                + RCS_MESSAGE_TABLE + "." + MESSAGE_ID_COLUMN + ", "
-                + RCS_MESSAGE_TABLE + "." + RCS_THREAD_ID_COLUMN + ", "
-                + RCS_MESSAGE_TABLE + "." + GLOBAL_ID_COLUMN + ", "
-                + RCS_MESSAGE_TABLE + "." + SUB_ID_COLUMN + ", "
-                + RCS_MESSAGE_TABLE + "." + STATUS_COLUMN + ", "
-                + RCS_MESSAGE_TABLE + "." + ORIGINATION_TIMESTAMP_COLUMN + ", "
-                + RCS_MESSAGE_TABLE + "." + MESSAGE_TEXT_COLUMN + ", "
-                + RCS_MESSAGE_TABLE + "." + LATITUDE_COLUMN + ", "
-                + RCS_MESSAGE_TABLE + "." + LONGITUDE_COLUMN + ", "
-                + RCS_INCOMING_MESSAGE_TABLE + "." + SENDER_PARTICIPANT_ID_COLUMN + ", "
-                + RCS_INCOMING_MESSAGE_TABLE + "." + ARRIVAL_TIMESTAMP_COLUMN + ", "
-                + RCS_INCOMING_MESSAGE_TABLE + "." + RcsIncomingMessageColumns.SEEN_TIMESTAMP_COLUMN
-                + ", "
-                + MESSAGE_TYPE_INCOMING + " AS " + MESSAGE_TYPE_COLUMN
-                + " FROM " + RCS_MESSAGE_TABLE + " INNER JOIN " + RCS_INCOMING_MESSAGE_TABLE
-                + " ON " + RCS_MESSAGE_TABLE + "." + MESSAGE_ID_COLUMN + "="
-                + RCS_INCOMING_MESSAGE_TABLE + "." + MESSAGE_ID_COLUMN);
-
-        // The following view inner joins incoming messages with all messages
-        //
-        // CREATE VIEW unified_incoming_message_view AS
-        //
-        // SELECT rcs_message.rcs_message_row_id,
-        //        rcs_message.rcs_thread_id,
-        //        rcs_message.rcs_message_global_id,
-        //        rcs_message.sub_id,
-        //        rcs_message.status,
-        //        rcs_message.origination_timestamp,
-        //        rcs_message.rcs_text,
-        //        rcs_message.latitude,
-        //        rcs_message.longitude,
-        //        rcs_incoming_message.sender_participant,
-        //        rcs_incoming_message.arrival_timestamp,
-        //        rcs_incoming_message.seen_timestamp,
-        //
-        // FROM rcs_message INNER JOIN rcs_incoming_message
-        //          ON rcs_message.rcs_message_row_id=rcs_incoming_message.rcs_message_row_id
-
-        db.execSQL("CREATE VIEW " + UNIFIED_INCOMING_MESSAGE_VIEW + " AS SELECT "
-                + RCS_MESSAGE_TABLE + "." + MESSAGE_ID_COLUMN + ", "
-                + RCS_MESSAGE_TABLE + "." + RCS_THREAD_ID_COLUMN + ", "
-                + RCS_MESSAGE_TABLE + "." + GLOBAL_ID_COLUMN + ", "
-                + RCS_MESSAGE_TABLE + "." + SUB_ID_COLUMN + ", "
-                + RCS_MESSAGE_TABLE + "." + STATUS_COLUMN + ", "
-                + RCS_MESSAGE_TABLE + "." + ORIGINATION_TIMESTAMP_COLUMN + ", "
-                + RCS_MESSAGE_TABLE + "." + MESSAGE_TEXT_COLUMN + ", "
-                + RCS_MESSAGE_TABLE + "." + LATITUDE_COLUMN + ", "
-                + RCS_MESSAGE_TABLE + "." + LONGITUDE_COLUMN + ", "
-                + RCS_INCOMING_MESSAGE_TABLE + "." + SENDER_PARTICIPANT_ID_COLUMN + ", "
-                + RCS_INCOMING_MESSAGE_TABLE + "." + ARRIVAL_TIMESTAMP_COLUMN + ", "
-                + RCS_INCOMING_MESSAGE_TABLE + "." + RcsIncomingMessageColumns.SEEN_TIMESTAMP_COLUMN
-                + " FROM " + RCS_MESSAGE_TABLE + " INNER JOIN " + RCS_INCOMING_MESSAGE_TABLE
-                + " ON " + RCS_MESSAGE_TABLE + "." + MESSAGE_ID_COLUMN + "="
-                + RCS_INCOMING_MESSAGE_TABLE + "." + MESSAGE_ID_COLUMN);
-
-        // The following view inner joins outgoing messages with all messages.
-        //
-        // CREATE VIEW unified_outgoing_message AS
-        //
-        // SELECT rcs_message.rcs_message_row_id,
-        //        rcs_message.rcs_thread_id,
-        //        rcs_message.rcs_message_global_id,
-        //        rcs_message.sub_id,
-        //        rcs_message.status,
-        //        rcs_message.origination_timestamp
-        //        rcs_message.rcs_text,
-        //        rcs_message.latitude,
-        //        rcs_message.longitude,
-        //
-        // FROM rcs_message INNER JOIN rcs_outgoing_message
-        //          ON rcs_message.rcs_message_row_id=rcs_outgoing_message.rcs_message_row_id
-
-        db.execSQL("CREATE VIEW " + UNIFIED_OUTGOING_MESSAGE_VIEW + " AS SELECT "
-                + RCS_MESSAGE_TABLE + "." + MESSAGE_ID_COLUMN + ", "
-                + RCS_MESSAGE_TABLE + "." + RCS_THREAD_ID_COLUMN + ", "
-                + RCS_MESSAGE_TABLE + "." + GLOBAL_ID_COLUMN + ", "
-                + RCS_MESSAGE_TABLE + "." + SUB_ID_COLUMN + ", "
-                + RCS_MESSAGE_TABLE + "." + STATUS_COLUMN + ", "
-                + RCS_MESSAGE_TABLE + "." + ORIGINATION_TIMESTAMP_COLUMN + ", "
-                + RCS_MESSAGE_TABLE + "." + MESSAGE_TEXT_COLUMN + ", "
-                + RCS_MESSAGE_TABLE + "." + LATITUDE_COLUMN + ", "
-                + RCS_MESSAGE_TABLE + "." + LONGITUDE_COLUMN
-                + " FROM " + RCS_MESSAGE_TABLE + " INNER JOIN " + RCS_OUTGOING_MESSAGE_TABLE
-                + " ON " + RCS_MESSAGE_TABLE + "." + MESSAGE_ID_COLUMN + "="
-                + RCS_OUTGOING_MESSAGE_TABLE + "." + MESSAGE_ID_COLUMN);
-
-        // Add triggers
-
-        // Delete the corresponding rcs_message row upon deleting a row in rcs_incoming_message
-        //
-        // CREATE TRIGGER delete_common_message_after_incoming
-        //  AFTER DELETE ON rcs_incoming_message
-        // BEGIN
-        //  DELETE FROM rcs_message WHERE rcs_message.rcs_message_row_id=OLD.rcs_message_row_id;
-        // END
-        db.execSQL("CREATE TRIGGER deleteCommonMessageAfterIncoming AFTER DELETE ON "
-                + RCS_INCOMING_MESSAGE_TABLE + " BEGIN DELETE FROM " + RCS_MESSAGE_TABLE
-                + " WHERE " + RCS_MESSAGE_TABLE + "." + MESSAGE_ID_COLUMN + "=OLD."
-                + MESSAGE_ID_COLUMN + "; END");
-
-        // Delete the corresponding rcs_message row upon deleting a row in rcs_outgoing_message
-        //
-        // CREATE TRIGGER delete_common_message_after_outgoing
-        //  AFTER DELETE ON rcs_outgoing_message
-        // BEGIN
-        //  DELETE FROM rcs_message WHERE rcs_message.rcs_message_row_id=OLD.rcs_message_row_id;
-        // END
-        db.execSQL("CREATE TRIGGER deleteCommonMessageAfterOutgoing AFTER DELETE ON "
-                + RCS_OUTGOING_MESSAGE_TABLE + " BEGIN DELETE FROM " + RCS_MESSAGE_TABLE
-                + " WHERE " + RCS_MESSAGE_TABLE + "." + MESSAGE_ID_COLUMN + "=OLD."
-                + MESSAGE_ID_COLUMN + "; END");
-    }
-
-    RcsProviderMessageHelper(SQLiteOpenHelper sqLiteOpenHelper) {
-        mSqLiteOpenHelper = sqLiteOpenHelper;
-    }
-
-    Cursor queryMessages(Bundle bundle) {
-        RcsMessageQueryParams queryParameters = null;
-        RcsQueryContinuationToken continuationToken = null;
-
-        if (bundle != null) {
-            queryParameters = bundle.getParcelable(MESSAGE_QUERY_PARAMETERS_KEY);
-            continuationToken = bundle.getParcelable(QUERY_CONTINUATION_TOKEN);
-        }
-
-        if (continuationToken != null) {
-            return RcsProviderUtil.performContinuationQuery(mSqLiteOpenHelper.getReadableDatabase(),
-                    continuationToken);
-        }
-
-        // if no parameters were entered, build an empty query parameters object
-        if (queryParameters == null) {
-            queryParameters = new RcsMessageQueryParams.Builder().build();
-        }
-
-        return performInitialQuery(queryParameters);
-    }
-
-    private Cursor performInitialQuery(RcsMessageQueryParams queryParameters) {
-        SQLiteDatabase db = mSqLiteOpenHelper.getReadableDatabase();
-
-        StringBuilder rawQuery = new StringBuilder("SELECT * FROM ").append(UNIFIED_MESSAGE_VIEW);
-
-        int messageType = queryParameters.getMessageType();
-        String messageLike = queryParameters.getMessageLike();
-        int threadId = queryParameters.getThreadId();
-
-        boolean isMessageLikePresent = !TextUtils.isEmpty(messageLike);
-        boolean isMessageTypeFiltered = (messageType == MESSAGE_TYPE_INCOMING)
-                || (messageType == MESSAGE_TYPE_OUTGOING);
-        boolean isThreadFiltered = threadId != THREAD_ID_NOT_SET;
-
-        if (isMessageLikePresent || isMessageTypeFiltered || isThreadFiltered) {
-            rawQuery.append(" WHERE ");
-        }
-
-        if (messageType == MESSAGE_TYPE_INCOMING) {
-            rawQuery.append(MESSAGE_TYPE_COLUMN).append("=").append(MESSAGE_TYPE_INCOMING);
-        } else if (messageType == MESSAGE_TYPE_OUTGOING) {
-            rawQuery.append(MESSAGE_TYPE_COLUMN).append("=").append(MESSAGE_TYPE_OUTGOING);
-        }
-
-        if (isMessageLikePresent) {
-            if (isMessageTypeFiltered) {
-                rawQuery.append(" AND ");
-            }
-            rawQuery.append(MESSAGE_TEXT_COLUMN).append(" LIKE \"").append(messageLike)
-                    .append("\"");
-        }
-
-        if (isThreadFiltered) {
-            if (isMessageLikePresent || isMessageTypeFiltered) {
-                rawQuery.append(" AND ");
-            }
-            rawQuery.append(RCS_THREAD_ID_COLUMN).append("=").append(threadId);
-        }
-
-        // TODO - figure out a way to see if this message has file transfer or not. Ideally we
-        // should join the unified table with file transfer table, but using a trigger to change a
-        // flag on rcs_message would also work
-
-        rawQuery.append(" ORDER BY ");
-
-        int sortingProperty = queryParameters.getSortingProperty();
-        if (sortingProperty == RcsMessageQueryParams.SORT_BY_TIMESTAMP) {
-            rawQuery.append(ORIGINATION_TIMESTAMP_COLUMN);
-        } else {
-            rawQuery.append(MESSAGE_ID_COLUMN);
-        }
-
-        rawQuery.append(queryParameters.getSortDirection() ? " ASC " : " DESC ");
-
-        RcsProviderUtil.appendLimit(rawQuery, queryParameters.getLimit());
-        String rawQueryAsString = rawQuery.toString();
-        Cursor cursor = db.rawQuery(rawQueryAsString, null);
-
-        // If the query was paginated, build the next query
-        int limit = queryParameters.getLimit();
-        if (limit > 0) {
-            RcsProviderUtil.createContinuationTokenBundle(cursor,
-                    new RcsQueryContinuationToken(MESSAGE_QUERY_CONTINUATION_TOKEN_TYPE,
-                            rawQueryAsString, limit, limit), QUERY_CONTINUATION_TOKEN);
-        }
-
-        return cursor;
-    }
-
-    Cursor queryUnifiedMessageWithId(Uri uri) {
-        return queryUnifiedMessageWithSelection(getMessageIdSelection(uri), null);
-    }
-
-    Cursor queryUnifiedMessageWithIdInThread(Uri uri) {
-        return queryUnifiedMessageWithSelection(getMessageIdSelectionInThreadUri(uri), null);
-    }
-
-    Cursor queryUnifiedMessageWithSelection(String selection, String[] selectionArgs) {
-        SQLiteDatabase db = mSqLiteOpenHelper.getReadableDatabase();
-        return db.query(UNIFIED_MESSAGE_VIEW, null, selection, selectionArgs, null, null, null,
-                null);
-    }
-
-    Cursor queryIncomingMessageWithId(Uri uri) {
-        return queryIncomingMessageWithSelection(getMessageIdSelection(uri), null);
-    }
-
-    Cursor queryIncomingMessageWithSelection(String selection, String[] selectionArgs) {
-        SQLiteDatabase db = mSqLiteOpenHelper.getReadableDatabase();
-        return db.query(UNIFIED_INCOMING_MESSAGE_VIEW, null, selection, selectionArgs, null, null,
-                null, null);
-    }
-
-    Cursor queryOutgoingMessageWithId(Uri uri) {
-        return queryOutgoingMessageWithSelection(getMessageIdSelection(uri), null);
-    }
-
-    Cursor queryOutgoingMessageWithSelection(String selection, String[] selectionArgs) {
-        SQLiteDatabase db = mSqLiteOpenHelper.getReadableDatabase();
-        return db.query(UNIFIED_OUTGOING_MESSAGE_VIEW, null, selection, selectionArgs, null, null,
-                null, null);
-    }
-
-    Cursor queryAllMessagesOnThread(Uri uri, String selection, String[] selectionArgs) {
-        SQLiteDatabase db = mSqLiteOpenHelper.getReadableDatabase();
-
-        String appendedSelection = appendThreadIdToSelection(uri, selection);
-        return db.query(UNIFIED_MESSAGE_VIEW, null, appendedSelection, null, null, null, null);
-    }
-
-    Uri insertMessageOnThread(Uri uri, ContentValues valuesParameter, boolean isIncoming,
-            boolean is1To1) {
-        SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-
-        String threadId = RcsProviderThreadHelper.getThreadIdFromUri(uri);
-        ContentValues values = new ContentValues(valuesParameter);
-        values.put(RCS_THREAD_ID_COLUMN, Integer.parseInt(threadId));
-
-        db.beginTransaction();
-
-        ContentValues subMessageTableValues = new ContentValues();
-        if (isIncoming) {
-            subMessageTableValues = getIncomingMessageValues(values);
-        }
-
-        long rowId;
-        try {
-            rowId = db.insert(RCS_MESSAGE_TABLE, MESSAGE_ID_COLUMN, values);
-            if (rowId == INSERTION_FAILED) {
-                return null;
-            }
-
-            subMessageTableValues.put(MESSAGE_ID_COLUMN, rowId);
-            long tempId = db.insert(
-                    isIncoming ? RCS_INCOMING_MESSAGE_TABLE : RCS_OUTGOING_MESSAGE_TABLE,
-                    MESSAGE_ID_COLUMN, subMessageTableValues);
-            if (tempId == INSERTION_FAILED) {
-                return null;
-            }
-
-            // if the thread is outgoing, insert message deliveries
-            if (!isIncoming && !insertMessageDeliveriesForOutgoingMessageCreation(db, tempId,
-                    threadId)) {
-                return null;
-            }
-
-            db.setTransactionSuccessful();
-        } finally {
-            db.endTransaction();
-        }
-
-        values.remove(RCS_THREAD_ID_COLUMN);
-
-        String threadPart =  is1To1 ? RCS_1_TO_1_THREAD_URI_PART : RCS_GROUP_THREAD_URI_PART;
-        String messagePart = isIncoming ? INCOMING_MESSAGE_URI_PART : OUTGOING_MESSAGE_URI_PART;
-
-        return CONTENT_AND_AUTHORITY.buildUpon().appendPath(threadPart).appendPath(threadId).
-                appendPath(messagePart).appendPath(Long.toString(rowId)).build();
-    }
-
-    // Tries to insert deliveries for outgoing message, returns false if it fails.
-    private boolean insertMessageDeliveriesForOutgoingMessageCreation(
-            SQLiteDatabase dbInTransaction, long messageId, String threadId) {
-        try (Cursor participantsInThreadCursor = dbInTransaction.query(
-                RCS_PARTICIPANT_THREAD_JUNCTION_TABLE, null, RCS_THREAD_ID_COLUMN + "=?",
-                new String[]{threadId}, null, null, null)) {
-            if (participantsInThreadCursor == null) {
-                return false;
-            }
-
-            while (participantsInThreadCursor.moveToNext()) {
-                String participantId = participantsInThreadCursor.getString(
-                        participantsInThreadCursor.getColumnIndex(
-                                RCS_PARTICIPANT_ID_COLUMN));
-
-                long insertionRow = insertMessageDelivery(Long.toString(messageId), participantId,
-                        new ContentValues());
-
-                if (insertionRow == INSERTION_FAILED) {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    long insertMessageDelivery(Uri uri, ContentValues values) {
-        String messageId = getMessageIdFromUri(uri);
-        String participantId = getParticipantIdFromDeliveryUri(uri);
-        return insertMessageDelivery(messageId, participantId, values);
-    }
-
-    private long insertMessageDelivery(String messageId, String participantId,
-            ContentValues valuesParameter) {
-        ContentValues values = new ContentValues(valuesParameter);
-        values.put(MESSAGE_ID_COLUMN, messageId);
-        values.put(RCS_PARTICIPANT_ID_COLUMN, participantId);
-
-        SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-        return db.insert(RCS_MESSAGE_DELIVERY_TABLE, MESSAGE_ID_COLUMN, values);
-    }
-
-    int updateDelivery(Uri uri, ContentValues contentValues) {
-        String messageId = getMessageIdFromUri(uri);
-        String participantId = getParticipantIdFromDeliveryUri(uri);
-
-        SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-        return db.update(RCS_MESSAGE_DELIVERY_TABLE, contentValues,
-                MESSAGE_ID_COLUMN + "=? AND " + RCS_PARTICIPANT_ID_COLUMN + "=?",
-                new String[]{messageId, participantId});
-    }
-
-    int deleteIncomingMessageWithId(Uri uri) {
-        return deleteIncomingMessageWithSelection(getMessageIdSelection(uri), null);
-    }
-
-    int deleteIncomingMessageWithSelection(String selection, String[] selectionArgs) {
-        SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-        return db.delete(RCS_INCOMING_MESSAGE_TABLE, selection, selectionArgs);
-    }
-
-    int deleteOutgoingMessageWithId(Uri uri) {
-        return deleteOutgoingMessageWithSelection(getMessageIdSelection(uri), null);
-    }
-
-    int deleteOutgoingMessageWithSelection(String selection, String[] selectionArgs) {
-        SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-        return db.delete(RCS_OUTGOING_MESSAGE_TABLE, selection, selectionArgs);
-    }
-
-    int updateIncomingMessage(Uri uri, ContentValues values) {
-        SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-
-        ContentValues incomingMessageValues = getIncomingMessageValues(values);
-
-        int updateCountInIncoming = 0;
-        int updateCountInCommon = 0;
-        db.beginTransaction();
-        if (!incomingMessageValues.isEmpty()) {
-            updateCountInIncoming = db.update(RCS_INCOMING_MESSAGE_TABLE, incomingMessageValues,
-                    getMessageIdSelection(uri), null);
-        }
-        if (!values.isEmpty()) {
-            updateCountInCommon = db.update(RCS_MESSAGE_TABLE, values, getMessageIdSelection(uri),
-                    null);
-        }
-        db.setTransactionSuccessful();
-        db.endTransaction();
-
-        return Math.max(updateCountInIncoming, updateCountInCommon);
-    }
-
-    int updateOutgoingMessage(Uri uri, ContentValues values) {
-        SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-        return db.update(RCS_MESSAGE_TABLE, values, getMessageIdSelection(uri), null);
-    }
-
-    Cursor queryOutgoingMessageDeliveries(Uri uri) {
-        String messageId = getMessageIdFromUri(uri);
-
-        SQLiteDatabase db = mSqLiteOpenHelper.getReadableDatabase();
-        return db.query(RCS_MESSAGE_DELIVERY_TABLE, null, MESSAGE_ID_COLUMN + "=?",
-                new String[]{messageId}, null, null, null);
-    }
-
-    Cursor queryFileTransfer(Uri uri) {
-        SQLiteDatabase db = mSqLiteOpenHelper.getReadableDatabase();
-        return db.query(RCS_FILE_TRANSFER_TABLE, null, FILE_TRANSFER_ID_COLUMN + "=?",
-                new String[]{getFileTransferIdFromUri(uri)}, null, null, null, null);
-    }
-
-    long insertFileTransferToMessage(Uri uri, ContentValues values) {
-        String messageId = getMessageIdFromUri(uri);
-        values.put(MESSAGE_ID_COLUMN, messageId);
-
-        SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-        long rowId = db.insert(RCS_FILE_TRANSFER_TABLE, MESSAGE_ID_COLUMN, values);
-        values.remove(MESSAGE_ID_COLUMN);
-
-        if (rowId == INSERTION_FAILED) {
-            rowId = TRANSACTION_FAILED;
-        }
-
-        return rowId;
-    }
-
-    int deleteFileTransfer(Uri uri) {
-        SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-        return db.delete(RCS_FILE_TRANSFER_TABLE, FILE_TRANSFER_ID_COLUMN + "=?",
-                new String[]{getFileTransferIdFromUri(uri)});
-    }
-
-    int updateFileTransfer(Uri uri, ContentValues values) {
-        SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-        return db.update(RCS_FILE_TRANSFER_TABLE, values,
-                FILE_TRANSFER_ID_COLUMN + "=?", new String[]{getFileTransferIdFromUri(uri)});
-    }
-
-    /**
-     * Removes the incoming message values out of all values and returns as a separate content
-     * values object.
-     */
-    private ContentValues getIncomingMessageValues(ContentValues allValues) {
-        ContentValues incomingMessageValues = new ContentValues();
-
-        if (allValues.containsKey(SENDER_PARTICIPANT_ID_COLUMN)) {
-            incomingMessageValues.put(SENDER_PARTICIPANT_ID_COLUMN,
-                    allValues.getAsInteger(SENDER_PARTICIPANT_ID_COLUMN));
-            allValues.remove(SENDER_PARTICIPANT_ID_COLUMN);
-        }
-
-        if (allValues.containsKey(ARRIVAL_TIMESTAMP_COLUMN)) {
-            incomingMessageValues.put(
-                    ARRIVAL_TIMESTAMP_COLUMN, allValues.getAsLong(ARRIVAL_TIMESTAMP_COLUMN));
-            allValues.remove(ARRIVAL_TIMESTAMP_COLUMN);
-        }
-
-        if (allValues.containsKey(RcsIncomingMessageColumns.SEEN_TIMESTAMP_COLUMN)) {
-            incomingMessageValues.put(
-                    RcsIncomingMessageColumns.SEEN_TIMESTAMP_COLUMN,
-                    allValues.getAsLong(RcsIncomingMessageColumns.SEEN_TIMESTAMP_COLUMN));
-            allValues.remove(RcsIncomingMessageColumns.SEEN_TIMESTAMP_COLUMN);
-        }
-
-        return incomingMessageValues;
-    }
-
-    private String appendThreadIdToSelection(Uri uri, String selection) {
-        String threadIdSelection = RCS_THREAD_ID_COLUMN + "=" + getThreadIdFromUri(uri);
-
-        if (TextUtils.isEmpty(selection)) {
-            return threadIdSelection;
-        }
-
-        return "(" + selection + ") AND " + threadIdSelection;
-    }
-
-    private String getMessageIdSelection(Uri uri) {
-        return MESSAGE_ID_COLUMN + "=" + getMessageIdFromUri(uri);
-    }
-
-    private String getMessageIdSelectionInThreadUri(Uri uri) {
-        return MESSAGE_ID_COLUMN + "=" + getMessageIdFromThreadUri(uri);
-    }
-
-    private String getMessageIdFromUri(Uri uri) {
-        return uri.getPathSegments().get(MESSAGE_ID_INDEX_IN_URI);
-    }
-
-    private String getFileTransferIdFromUri(Uri uri) {
-        // this works because messages and file transfer uri's have the same indices.
-        return getMessageIdFromUri(uri);
-    }
-
-    private String getParticipantIdFromDeliveryUri(Uri uri) {
-        // this works because messages in threads and participants in deliveries have the same
-        // indices.
-        return getMessageIdFromThreadUri(uri);
-    }
-
-    private String getMessageIdFromThreadUri(Uri uri) {
-        return uri.getPathSegments().get(MESSAGE_ID_INDEX_IN_THREAD_URI);
-    }
-}
diff --git a/src/com/android/providers/telephony/RcsProviderParticipantHelper.java b/src/com/android/providers/telephony/RcsProviderParticipantHelper.java
deleted file mode 100644
index ab23d6d..0000000
--- a/src/com/android/providers/telephony/RcsProviderParticipantHelper.java
+++ /dev/null
@@ -1,387 +0,0 @@
-/*
- * 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 static android.provider.Telephony.CanonicalAddressesColumns.ADDRESS;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.CANONICAL_ADDRESS_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.RCS_ALIAS_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.RCS_PARTICIPANT_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.RCS_PARTICIPANT_URI_PART;
-import static android.provider.Telephony.RcsColumns.RcsParticipantHelpers.RCS_PARTICIPANT_WITH_ADDRESS_VIEW;
-import static android.provider.Telephony.RcsColumns.RcsParticipantHelpers.RCS_PARTICIPANT_WITH_THREAD_VIEW;
-import static android.provider.Telephony.RcsColumns.RcsThreadColumns.RCS_THREAD_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.TRANSACTION_FAILED;
-import static android.telephony.ims.RcsParticipantQueryParams.PARTICIPANT_QUERY_PARAMETERS_KEY;
-
-import static android.telephony.ims.RcsQueryContinuationToken.PARTICIPANT_QUERY_CONTINUATION_TOKEN_TYPE;
-import static android.telephony.ims.RcsQueryContinuationToken.QUERY_CONTINUATION_TOKEN;
-import static com.android.providers.telephony.RcsProvider.GROUP_THREAD_URI_PREFIX;
-import static com.android.providers.telephony.RcsProvider.RCS_PARTICIPANT_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_PARTICIPANT_THREAD_JUNCTION_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_THREAD_TABLE;
-import static com.android.providers.telephony.RcsProvider.TAG;
-import static com.android.providers.telephony.RcsProviderThreadHelper.getThreadIdFromUri;
-import static com.android.providers.telephony.RcsProviderUtil.INSERTION_FAILED;
-
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.net.Uri;
-import android.os.Bundle;
-import android.telephony.ims.RcsParticipantQueryParams;
-import android.telephony.ims.RcsQueryContinuationToken;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-/**
- * Constants and helpers related to participants for {@link RcsProvider} to keep the code clean.
- *
- * @hide
- */
-class RcsProviderParticipantHelper {
-    private static final int PARTICIPANT_ID_INDEX_IN_URI = 1;
-    private static final int PARTICIPANT_ID_INDEX_IN_THREAD_URI = 3;
-
-    @VisibleForTesting
-    public static void createParticipantTables(SQLiteDatabase db) {
-        Log.d(TAG, "Creating participant tables");
-
-        // create participant tables
-        db.execSQL("CREATE TABLE " + RCS_PARTICIPANT_TABLE + " (" +
-                RCS_PARTICIPANT_ID_COLUMN + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
-                CANONICAL_ADDRESS_ID_COLUMN + " INTEGER ," +
-                RCS_ALIAS_COLUMN + " TEXT, " +
-                "FOREIGN KEY(" + CANONICAL_ADDRESS_ID_COLUMN + ") "
-                + "REFERENCES canonical_addresses(_id)" +
-                ");");
-
-        db.execSQL("CREATE TABLE " + RCS_PARTICIPANT_THREAD_JUNCTION_TABLE + " (" +
-                RCS_THREAD_ID_COLUMN + " INTEGER, " +
-                RCS_PARTICIPANT_ID_COLUMN + " INTEGER, " +
-                "CONSTRAINT thread_participant PRIMARY KEY("
-                + RCS_THREAD_ID_COLUMN + ", " + RCS_PARTICIPANT_ID_COLUMN + "), " +
-                "FOREIGN KEY(" + RCS_THREAD_ID_COLUMN
-                + ") REFERENCES " + RCS_THREAD_TABLE + "(" + RCS_THREAD_ID_COLUMN + "), " +
-                "FOREIGN KEY(" + RCS_PARTICIPANT_ID_COLUMN
-                + ") REFERENCES " + RCS_PARTICIPANT_TABLE + "(" + RCS_PARTICIPANT_ID_COLUMN + "))");
-
-        // create views
-
-        // The following view joins rcs_participant table with canonical_addresses table to add the
-        // actual address of a participant in the result.
-        db.execSQL("CREATE VIEW " + RCS_PARTICIPANT_WITH_ADDRESS_VIEW + " AS SELECT "
-                + "rcs_participant.rcs_participant_id, rcs_participant.canonical_address_id, "
-                + "rcs_participant.rcs_alias, canonical_addresses.address FROM rcs_participant "
-                + "LEFT JOIN canonical_addresses ON "
-                + "rcs_participant.canonical_address_id=canonical_addresses._id");
-
-        // The following view is the rcs_participant_with_address_view above, plus the information
-        // on which threads this participant contributes to, to enable getting participants of a
-        // thread
-        db.execSQL("CREATE VIEW " + RCS_PARTICIPANT_WITH_THREAD_VIEW + " AS SELECT "
-                + "rcs_participant.rcs_participant_id, rcs_participant.canonical_address_id, "
-                + "rcs_participant.rcs_alias, canonical_addresses.address, rcs_thread_participant"
-                + ".rcs_thread_id FROM rcs_participant LEFT JOIN canonical_addresses ON "
-                + "rcs_participant.canonical_address_id=canonical_addresses._id LEFT JOIN "
-                + "rcs_thread_participant ON rcs_participant.rcs_participant_id="
-                + "rcs_thread_participant.rcs_participant_id");
-
-        // TODO - create indexes for faster querying
-    }
-
-    private final SQLiteOpenHelper mSqLiteOpenHelper;
-
-    RcsProviderParticipantHelper(SQLiteOpenHelper sqLiteOpenHelper) {
-        mSqLiteOpenHelper = sqLiteOpenHelper;
-    }
-
-    Cursor queryParticipant(Bundle bundle) {
-        RcsParticipantQueryParams queryParameters = null;
-        RcsQueryContinuationToken continuationToken = null;
-
-        if (bundle != null) {
-            queryParameters = bundle.getParcelable(PARTICIPANT_QUERY_PARAMETERS_KEY);
-            continuationToken = bundle.getParcelable(QUERY_CONTINUATION_TOKEN);
-        }
-
-        if (continuationToken != null) {
-            return RcsProviderUtil.performContinuationQuery(mSqLiteOpenHelper.getReadableDatabase(),
-                    continuationToken);
-        }
-
-        if (queryParameters == null) {
-            queryParameters = new RcsParticipantQueryParams.Builder().build();
-        }
-
-        return performInitialQuery(queryParameters);
-    }
-
-    private Cursor performInitialQuery(RcsParticipantQueryParams queryParameters) {
-        SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-
-        StringBuilder rawQuery = buildInitialRawQuery(queryParameters);
-        RcsProviderUtil.appendLimit(rawQuery, queryParameters.getLimit());
-        String rawQueryAsString = rawQuery.toString();
-        Cursor cursor = db.rawQuery(rawQueryAsString, null);
-
-        // If the query was paginated, build the next query
-        int limit = queryParameters.getLimit();
-        if (limit > 0) {
-            RcsProviderUtil.createContinuationTokenBundle(cursor,
-                    new RcsQueryContinuationToken(PARTICIPANT_QUERY_CONTINUATION_TOKEN_TYPE,
-                            rawQueryAsString, limit, limit), QUERY_CONTINUATION_TOKEN);
-        }
-
-        return cursor;
-    }
-
-    private StringBuilder buildInitialRawQuery(RcsParticipantQueryParams queryParameters) {
-        StringBuilder rawQuery = new StringBuilder("SELECT * FROM ");
-
-        boolean isThreadFiltered = queryParameters.getThreadId() > 0;
-
-        if (isThreadFiltered) {
-            rawQuery.append(RCS_PARTICIPANT_WITH_THREAD_VIEW);
-        } else {
-            rawQuery.append(RCS_PARTICIPANT_WITH_ADDRESS_VIEW);
-        }
-
-        boolean isAliasFiltered = !TextUtils.isEmpty(queryParameters.getAliasLike());
-        boolean isCanonicalAddressFiltered = !TextUtils.isEmpty(
-                queryParameters.getCanonicalAddressLike());
-
-        if (isAliasFiltered || isCanonicalAddressFiltered || isThreadFiltered) {
-            rawQuery.append(" WHERE ");
-        }
-
-        if (isAliasFiltered) {
-            rawQuery.append(RCS_ALIAS_COLUMN).append(" LIKE \"").append(
-                    queryParameters.getAliasLike()).append("\"");
-        }
-
-        if (isCanonicalAddressFiltered) {
-            if (isAliasFiltered) {
-                rawQuery.append(" AND ");
-            }
-            rawQuery.append(ADDRESS).append(" LIKE \"").append(
-                    queryParameters.getCanonicalAddressLike()).append("\"");
-        }
-
-        if (isThreadFiltered) {
-            if (isAliasFiltered || isCanonicalAddressFiltered) {
-                rawQuery.append(" AND ");
-            }
-            rawQuery.append(RCS_THREAD_ID_COLUMN).append("=").append(queryParameters.getThreadId());
-        }
-
-        rawQuery.append(" ORDER BY ");
-
-        int sortingProperty = queryParameters.getSortingProperty();
-        if (sortingProperty == RcsParticipantQueryParams.SORT_BY_ALIAS) {
-            rawQuery.append(RCS_ALIAS_COLUMN);
-        } else if (sortingProperty == RcsParticipantQueryParams.SORT_BY_CANONICAL_ADDRESS) {
-            rawQuery.append(ADDRESS);
-        } else {
-            rawQuery.append(RCS_PARTICIPANT_ID_COLUMN);
-        }
-        rawQuery.append(queryParameters.getSortDirection() ? " ASC " : " DESC ");
-
-        return rawQuery;
-    }
-
-    Cursor queryParticipantWithId(Uri uri, String[] projection) {
-        SQLiteDatabase db = mSqLiteOpenHelper.getReadableDatabase();
-        return db.query(RCS_PARTICIPANT_WITH_ADDRESS_VIEW, projection,
-                getParticipantIdSelection(uri), null, null, null, null);
-    }
-
-    Cursor queryParticipantIn1To1Thread(Uri uri) {
-        String threadId = getThreadIdFromUri(uri);
-        SQLiteDatabase db = mSqLiteOpenHelper.getReadableDatabase();
-
-        return db.rawQuery(
-                "  SELECT * "
-                        + "FROM rcs_participant "
-                        + "WHERE rcs_participant.rcs_participant_id = ("
-                        + "  SELECT rcs_thread_participant.rcs_participant_id "
-                        + "  FROM rcs_thread_participant "
-                        + "  WHERE rcs_thread_participant.rcs_thread_id=" + threadId + ")", null);
-    }
-
-    Cursor queryParticipantsInGroupThread(Uri uri) {
-        String threadId = getThreadIdFromUri(uri);
-        SQLiteDatabase db = mSqLiteOpenHelper.getReadableDatabase();
-
-        return db.rawQuery("  SELECT * "
-                + "FROM rcs_participant "
-                + "WHERE rcs_participant.rcs_participant_id = ("
-                + "  SELECT rcs_participant_id "
-                + "  FROM rcs_thread_participant "
-                + "  WHERE rcs_thread_id= " + threadId + ")", null);
-    }
-
-    Cursor queryParticipantInGroupThreadWithId(Uri uri) {
-        String threadId = getThreadIdFromUri(uri);
-        String participantId = getParticipantIdFromUri(uri);
-        SQLiteDatabase db = mSqLiteOpenHelper.getReadableDatabase();
-
-        return db.rawQuery("  SELECT * "
-                        + "FROM rcs_participant "
-                        + "WHERE rcs_participant.rcs_participant_id = ("
-                        + "  SELECT rcs_participant_id "
-                        + "  FROM rcs_thread_participant "
-                        + "  WHERE rcs_thread_id=? AND rcs_participant_id=?)",
-                new String[]{threadId, participantId});
-    }
-
-    long insertParticipant(ContentValues contentValues) {
-        if (!contentValues.containsKey(CANONICAL_ADDRESS_ID_COLUMN) || TextUtils.isEmpty(
-                contentValues.getAsString(CANONICAL_ADDRESS_ID_COLUMN))) {
-            Log.e(TAG,
-                    "RcsProviderParticipantHelper: Inserting participants without canonical "
-                            + "address is not supported");
-            return TRANSACTION_FAILED;
-        }
-        SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-        long rowId = db.insert(RCS_PARTICIPANT_TABLE, RCS_PARTICIPANT_ID_COLUMN, contentValues);
-        Log.e(TAG, "Inserted participant with rowId=" + rowId);
-        if (rowId < 0) {
-            return TRANSACTION_FAILED;
-        }
-        return rowId;
-    }
-
-    /**
-     * Inserts a participant into group thread. This function returns the participant ID instead of
-     * the row id in the junction table
-     */
-    long insertParticipantIntoGroupThread(ContentValues values) {
-        if (!values.containsKey(RCS_THREAD_ID_COLUMN) || !values.containsKey(
-                RCS_PARTICIPANT_ID_COLUMN)) {
-            Log.e(TAG, "RcsProviderParticipantHelper: Cannot insert participant into group.");
-            return TRANSACTION_FAILED;
-        }
-        SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-        long insertedRowId = db.insert(RCS_PARTICIPANT_THREAD_JUNCTION_TABLE,
-                RCS_PARTICIPANT_ID_COLUMN,
-                values);
-
-        if (insertedRowId == INSERTION_FAILED) {
-            return TRANSACTION_FAILED;
-        }
-
-        return values.getAsLong(RCS_PARTICIPANT_ID_COLUMN);
-    }
-
-    /**
-     * Inserts a participant into group thread. This function returns the participant ID instead of
-     * the row id in the junction table
-     */
-    long insertParticipantIntoGroupThreadWithId(Uri uri) {
-        String threadId = getThreadIdFromUri(uri);
-        String participantId = getParticipantIdFromUri(uri);
-        SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-
-        ContentValues contentValues = new ContentValues(2);
-        contentValues.put(RCS_THREAD_ID_COLUMN, threadId);
-        contentValues.put(RCS_PARTICIPANT_ID_COLUMN, participantId);
-
-        long insertedRowId = db.insert(
-                RCS_PARTICIPANT_THREAD_JUNCTION_TABLE, RCS_PARTICIPANT_ID_COLUMN, contentValues);
-
-        if (insertedRowId == INSERTION_FAILED) {
-            return TRANSACTION_FAILED;
-        }
-
-        return Long.parseLong(participantId);
-    }
-
-    int deleteParticipantWithId(Uri uri) {
-        String participantId = uri.getPathSegments().get(PARTICIPANT_ID_INDEX_IN_URI);
-        SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-
-        // See if this participant is involved in any threads
-        Cursor cursor = db.query(RCS_PARTICIPANT_THREAD_JUNCTION_TABLE, null,
-                RCS_PARTICIPANT_ID_COLUMN + "=?", new String[]{participantId}, null, null, null);
-
-        int participatingThreadCount = 0;
-        if (cursor != null) {
-            participatingThreadCount = cursor.getCount();
-            cursor.close();
-        }
-
-        if (participatingThreadCount > 0) {
-            Log.e(TAG,
-                    "RcsProviderParticipantHelper: Can't delete participant while it is still in "
-                            + "RCS threads, uri:"
-                            + uri);
-            return 0;
-        }
-
-        return db.delete(RCS_PARTICIPANT_TABLE, RCS_PARTICIPANT_ID_COLUMN + "=?",
-                new String[]{participantId});
-    }
-
-    int deleteParticipantFromGroupThread(Uri uri) {
-        String threadId = getThreadIdFromUri(uri);
-        String participantId = getParticipantIdFromUri(uri);
-        SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-        // TODO check to remove owner
-        return db.delete(RCS_PARTICIPANT_THREAD_JUNCTION_TABLE,
-                RCS_THREAD_ID_COLUMN + "=? AND " + RCS_PARTICIPANT_ID_COLUMN + "=?",
-                new String[]{threadId, participantId});
-    }
-
-    int updateParticipant(ContentValues contentValues, String selection, String[] selectionArgs) {
-        if (contentValues.containsKey(RCS_PARTICIPANT_ID_COLUMN)) {
-            Log.e(TAG, "RcsProviderParticipantHelper: Updating participant id is not supported");
-            return 0;
-        }
-
-        SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-        return db.update(RCS_PARTICIPANT_TABLE, contentValues, selection, selectionArgs);
-    }
-
-    int updateParticipantWithId(ContentValues contentValues, Uri uri) {
-        return updateParticipant(contentValues, getParticipantIdSelection(uri), null);
-    }
-
-    private String getParticipantIdSelection(Uri uri) {
-        return RCS_PARTICIPANT_ID_COLUMN + "=" + uri.getPathSegments().get(
-                PARTICIPANT_ID_INDEX_IN_URI);
-    }
-
-    Uri getParticipantInThreadUri(ContentValues values, long rowId) {
-        if (values == null) {
-            return null;
-        }
-        Integer threadId = values.getAsInteger(RCS_THREAD_ID_COLUMN);
-        if (threadId == null) {
-            return null;
-        }
-
-        return GROUP_THREAD_URI_PREFIX.buildUpon().appendPath(
-                Integer.toString(threadId)).appendPath(RCS_PARTICIPANT_URI_PART).appendPath(
-                Long.toString(rowId)).build();
-    }
-
-    private String getParticipantIdFromUri(Uri uri) {
-        return uri.getPathSegments().get(PARTICIPANT_ID_INDEX_IN_THREAD_URI);
-    }
-}
diff --git a/src/com/android/providers/telephony/RcsProviderThreadHelper.java b/src/com/android/providers/telephony/RcsProviderThreadHelper.java
deleted file mode 100644
index c1a35ef..0000000
--- a/src/com/android/providers/telephony/RcsProviderThreadHelper.java
+++ /dev/null
@@ -1,503 +0,0 @@
-/*
- * 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 static android.provider.Telephony.RcsColumns.Rcs1To1ThreadColumns.FALLBACK_THREAD_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsGroupThreadColumns.CONFERENCE_URI_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsGroupThreadColumns.GROUP_ICON_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsGroupThreadColumns.GROUP_NAME_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsGroupThreadColumns.OWNER_PARTICIPANT_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.MESSAGE_TEXT_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.ORIGINATION_TIMESTAMP_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.STATUS_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.RCS_PARTICIPANT_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsThreadColumns.RCS_THREAD_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsUnifiedThreadColumns.THREAD_TYPE_COLUMN;
-import static android.provider.Telephony.RcsColumns.TRANSACTION_FAILED;
-import static android.telephony.ims.RcsQueryContinuationToken.QUERY_CONTINUATION_TOKEN;
-import static android.telephony.ims.RcsQueryContinuationToken.THREAD_QUERY_CONTINUATION_TOKEN_TYPE;
-import static android.telephony.ims.RcsThreadQueryParams.THREAD_QUERY_PARAMETERS_KEY;
-
-import static com.android.providers.telephony.RcsProvider.RCS_1_TO_1_THREAD_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_GROUP_THREAD_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_MESSAGE_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_PARTICIPANT_THREAD_JUNCTION_TABLE;
-import static com.android.providers.telephony.RcsProvider.RCS_THREAD_TABLE;
-import static com.android.providers.telephony.RcsProvider.TAG;
-import static com.android.providers.telephony.RcsProvider.UNIFIED_RCS_THREAD_VIEW;
-import static com.android.providers.telephony.RcsProviderUtil.INSERTION_FAILED;
-
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.net.Uri;
-import android.os.Bundle;
-import android.provider.BaseColumns;
-import android.telephony.ims.RcsQueryContinuationToken;
-import android.telephony.ims.RcsThreadQueryParams;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-/**
- * Constants and helpers related to threads for {@link RcsProvider} to keep the code clean.
- *
- * @hide
- */
-class RcsProviderThreadHelper {
-    private static final int THREAD_ID_INDEX_IN_URI = 1;
-
-    @VisibleForTesting
-    public static void createThreadTables(SQLiteDatabase db) {
-        Log.d(TAG, "Creating thread tables");
-
-        // Add the thread tables
-        db.execSQL("CREATE TABLE " + RCS_THREAD_TABLE + " (" +
-                RCS_THREAD_ID_COLUMN + " INTEGER PRIMARY KEY AUTOINCREMENT);");
-
-        db.execSQL("CREATE TABLE " + RCS_1_TO_1_THREAD_TABLE + " (" +
-                RCS_THREAD_ID_COLUMN + " INTEGER PRIMARY KEY, " +
-                FALLBACK_THREAD_ID_COLUMN + " INTEGER, " +
-                "FOREIGN KEY(" + RCS_THREAD_ID_COLUMN
-                + ") REFERENCES " + RCS_THREAD_TABLE + "(" + RCS_THREAD_ID_COLUMN + ")," +
-                "FOREIGN KEY(" + FALLBACK_THREAD_ID_COLUMN
-                + ") REFERENCES threads( " + BaseColumns._ID + "))");
-
-        db.execSQL("CREATE TABLE " + RCS_GROUP_THREAD_TABLE + " (" +
-                RCS_THREAD_ID_COLUMN + " INTEGER PRIMARY KEY, " +
-                OWNER_PARTICIPANT_COLUMN + " INTEGER, " +
-                GROUP_NAME_COLUMN + " TEXT, " +
-                GROUP_ICON_COLUMN + " TEXT, " +
-                CONFERENCE_URI_COLUMN + " TEXT, " +
-                "FOREIGN KEY(" + RCS_THREAD_ID_COLUMN
-                + ") REFERENCES " + RCS_THREAD_TABLE + "(" + RCS_THREAD_ID_COLUMN + "))");
-
-        // Add the views
-
-        // The following is a unified thread view. Since SQLite does not support right or full
-        // joins, we are using a union with null values for unused variables for each thread type.
-        // The thread_type column is an easy way to figure out whether the entry came from a 1 to 1
-        // thread or a group thread. The last message in each thread is appended to the table
-        // entries to figure out the latest threads and snippet text. We use COALESCE so that MAX()
-        // can take null values into account in order to have threads with no messages still
-        // represented here
-        //
-        // SELECT <1 to 1 thread and first message>
-        // FROM (
-        //     SELECT *
-        //     FROM rcs_1_to_1_thread LEFT JOIN rcs_message
-        //         ON rcs_1_to_1_thread.rcs_thread_id=rcs_message.rcs_thread_id)
-        // GROUP BY rcs_thread_id
-        // HAVING MAX(COALESCE(origination_timestamp,1))
-        //
-        // UNION
-        // SELECT <group thread and first message>
-        // FROM (
-        //     SELECT *
-        //     FROM rcs_group_thread LEFT JOIN rcs_message
-        //         ON rcs_group_thread.rcs_thread_id=rcs_message.rcs_thread_id)
-        // GROUP BY rcs_thread_id
-        // HAVING MAX(COALESCE(origination_timestamp,1))
-
-        db.execSQL("CREATE VIEW " + UNIFIED_RCS_THREAD_VIEW + " AS "
-                + "SELECT "
-                + RCS_THREAD_ID_COLUMN + ", "
-                + FALLBACK_THREAD_ID_COLUMN + ", "
-                + "null AS " + OWNER_PARTICIPANT_COLUMN + ", "
-                + "null AS " + GROUP_NAME_COLUMN + ", "
-                + "null AS " + GROUP_ICON_COLUMN + ", "
-                + "null AS " + CONFERENCE_URI_COLUMN + ", "
-                + "0 AS " + THREAD_TYPE_COLUMN + ", "
-                + ORIGINATION_TIMESTAMP_COLUMN + ", "
-                + MESSAGE_TEXT_COLUMN + ", "
-                + STATUS_COLUMN
-                + " FROM (SELECT * FROM "
-                + RCS_1_TO_1_THREAD_TABLE + " LEFT JOIN " + RCS_MESSAGE_TABLE
-                + " ON "
-                + RCS_1_TO_1_THREAD_TABLE + "." + RCS_THREAD_ID_COLUMN + "="
-                + RCS_MESSAGE_TABLE + "." + RCS_THREAD_ID_COLUMN + ")"
-                + " GROUP BY " + RCS_THREAD_ID_COLUMN
-                + " HAVING MAX(COALESCE("
-                + ORIGINATION_TIMESTAMP_COLUMN + ", 1))"
-                + " UNION SELECT "
-                + RCS_THREAD_ID_COLUMN + ", "
-                + "null AS " + FALLBACK_THREAD_ID_COLUMN + ", "
-                + OWNER_PARTICIPANT_COLUMN + ", "
-                + GROUP_NAME_COLUMN + ", "
-                + GROUP_ICON_COLUMN + ", "
-                + CONFERENCE_URI_COLUMN + ", "
-                + "1 AS " + THREAD_TYPE_COLUMN + ", "
-                + ORIGINATION_TIMESTAMP_COLUMN + ", "
-                + MESSAGE_TEXT_COLUMN + ", "
-                + STATUS_COLUMN
-                + " FROM (SELECT * FROM "
-                + RCS_GROUP_THREAD_TABLE + " LEFT JOIN " + RCS_MESSAGE_TABLE
-                + " ON "
-                + RCS_GROUP_THREAD_TABLE + "." + RCS_THREAD_ID_COLUMN + "="
-                + RCS_MESSAGE_TABLE + "." + RCS_THREAD_ID_COLUMN + ")"
-                + " GROUP BY " + RCS_THREAD_ID_COLUMN
-                + " HAVING MAX(COALESCE("
-                + ORIGINATION_TIMESTAMP_COLUMN + ", 1))");
-
-        // Add the triggers
-
-        // Delete the corresponding rcs_thread row upon deleting a row in rcs_1_to_1_thread
-        //
-        // CREATE TRIGGER deleteRcsThreadAfter1to1
-        //  AFTER DELETE ON rcs_1_to_1_thread
-        // BEGIN
-        //	DELETE FROM rcs_thread WHERE rcs_thread._id=OLD.rcs_thread_id;
-        // END
-        db.execSQL("CREATE TRIGGER deleteRcsThreadAfter1to1 AFTER DELETE ON "
-                + RCS_1_TO_1_THREAD_TABLE + " BEGIN DELETE FROM " + RCS_THREAD_TABLE + " WHERE "
-                + RCS_THREAD_TABLE + "." + RCS_THREAD_ID_COLUMN + "=OLD." + RCS_THREAD_ID_COLUMN
-                + "; END");
-
-        // Delete the corresponding rcs_thread row upon deleting a row in rcs_group_thread
-        //
-        // CREATE TRIGGER deleteRcsThreadAfter1to1
-        //  AFTER DELETE ON rcs_1_to_1_thread
-        // BEGIN
-        //	DELETE FROM rcs_thread WHERE rcs_thread._id=OLD.rcs_thread_id;
-        // END
-        db.execSQL("CREATE TRIGGER deleteRcsThreadAfterGroup AFTER DELETE ON "
-                + RCS_GROUP_THREAD_TABLE + " BEGIN DELETE FROM " + RCS_THREAD_TABLE + " WHERE "
-                + RCS_THREAD_TABLE + "." + RCS_THREAD_ID_COLUMN + "=OLD." + RCS_THREAD_ID_COLUMN
-                + "; END");
-
-        // Delete the junction table entries upon deleting a 1 to 1 thread
-        //
-        // CREATE TRIGGER delete1To1JunctionEntries
-        // AFTER
-        //  DELETE ON rcs_1_to_1_thread
-        // BEGIN
-        //  DELETE FROM
-        //   rcs_thread_participant
-        //  WHERE
-        //   rcs_thread_participant.rcs_thread_id = OLD.rcs_thread_id;
-        // END
-        db.execSQL("CREATE TRIGGER delete1To1JunctionEntries AFTER DELETE ON "
-                + RCS_1_TO_1_THREAD_TABLE + " BEGIN DELETE FROM "
-                + RCS_PARTICIPANT_THREAD_JUNCTION_TABLE + " WHERE "
-                + RCS_PARTICIPANT_THREAD_JUNCTION_TABLE + "." + RCS_THREAD_ID_COLUMN + "=OLD."
-                + RCS_THREAD_ID_COLUMN + "; END");
-
-        // Delete the junction table entries upon deleting a group thread
-        //
-        // CREATE TRIGGER delete1To1JunctionEntries
-        // AFTER
-        //  DELETE ON rcs_1_to_1_thread
-        // BEGIN
-        //  DELETE FROM
-        //   rcs_thread_participant
-        //  WHERE
-        //   rcs_thread_participant.rcs_thread_id = OLD.rcs_thread_id;
-        // END
-        db.execSQL("CREATE TRIGGER deleteGroupJunctionEntries AFTER DELETE ON "
-                + RCS_GROUP_THREAD_TABLE + " BEGIN DELETE FROM "
-                + RCS_PARTICIPANT_THREAD_JUNCTION_TABLE + " WHERE "
-                + RCS_PARTICIPANT_THREAD_JUNCTION_TABLE + "." + RCS_THREAD_ID_COLUMN + "=OLD."
-                +RCS_THREAD_ID_COLUMN + "; END");
-
-        // TODO - delete all messages in a thread after deleting a thread
-
-        // TODO - create indexes for faster querying
-    }
-
-    private final SQLiteOpenHelper mSqLiteOpenHelper;
-
-    RcsProviderThreadHelper(SQLiteOpenHelper sqLiteOpenHelper) {
-        mSqLiteOpenHelper = sqLiteOpenHelper;
-    }
-
-    Cursor queryUnifiedThread(Bundle bundle) {
-        RcsThreadQueryParams queryParameters = null;
-        RcsQueryContinuationToken continuationToken = null;
-        if (bundle != null) {
-            queryParameters = bundle.getParcelable(
-                    THREAD_QUERY_PARAMETERS_KEY);
-            continuationToken = bundle.getParcelable(QUERY_CONTINUATION_TOKEN);
-        }
-
-        if (continuationToken != null) {
-            return RcsProviderUtil.performContinuationQuery(mSqLiteOpenHelper.getReadableDatabase(),
-                    continuationToken);
-        }
-
-        if (queryParameters == null) {
-            queryParameters = new RcsThreadQueryParams.Builder().build();
-        }
-
-        return performInitialQuery(queryParameters);
-    }
-
-    private Cursor performInitialQuery(RcsThreadQueryParams queryParameters) {
-        if (queryParameters == null) {
-            // return everything for test purposes
-            queryParameters = new RcsThreadQueryParams.Builder().build();
-        }
-
-        SQLiteDatabase db = mSqLiteOpenHelper.getReadableDatabase();
-        StringBuilder rawQuery = new StringBuilder("SELECT * FROM ").append(
-                UNIFIED_RCS_THREAD_VIEW);
-
-        if (queryParameters.getThreadType() == RcsThreadQueryParams.THREAD_TYPE_1_TO_1) {
-            rawQuery.append(" WHERE ").append(THREAD_TYPE_COLUMN).append("=0");
-        } else if (queryParameters.getThreadType() == RcsThreadQueryParams.THREAD_TYPE_GROUP) {
-            rawQuery.append(" WHERE ").append(THREAD_TYPE_COLUMN).append("=1");
-        }
-
-        rawQuery.append(" ORDER BY ");
-
-        if (queryParameters.getSortingProperty() == RcsThreadQueryParams.SORT_BY_TIMESTAMP) {
-            rawQuery.append(ORIGINATION_TIMESTAMP_COLUMN);
-        } else {
-            rawQuery.append(RCS_THREAD_ID_COLUMN);
-        }
-
-        rawQuery.append(queryParameters.getSortDirection() ? " ASC " : " DESC ");
-        RcsProviderUtil.appendLimit(rawQuery, queryParameters.getLimit());
-
-        String rawQueryAsString = rawQuery.toString();
-        Cursor cursor = db.rawQuery(rawQueryAsString, null);
-
-        // If this is a paginated query, build the next query and return as a Cursor extra. Only do
-        // this if the current query returned a result.
-        int limit = queryParameters.getLimit();
-        if (limit > 0) {
-            RcsProviderUtil.createContinuationTokenBundle(cursor,
-                    new RcsQueryContinuationToken(THREAD_QUERY_CONTINUATION_TOKEN_TYPE,
-                            rawQueryAsString, limit, limit), QUERY_CONTINUATION_TOKEN);
-        }
-
-        return cursor;
-    }
-
-    Cursor queryUnifiedThreadUsingId(Uri uri, String[] projection) {
-        SQLiteDatabase db = mSqLiteOpenHelper.getReadableDatabase();
-        String threadId = getThreadIdFromUri(uri);
-
-        return db.query(UNIFIED_RCS_THREAD_VIEW, projection, RCS_THREAD_ID_COLUMN + "=?",
-                new String[]{threadId},
-                null, null, null);
-    }
-
-    Cursor query1to1Thread(String[] projection, String selection, String[] selectionArgs,
-            String sortOrder) {
-        SQLiteDatabase db = mSqLiteOpenHelper.getReadableDatabase();
-        return db.query(RCS_1_TO_1_THREAD_TABLE, projection, selection, selectionArgs, null,
-                null, sortOrder);
-    }
-
-    Cursor query1To1ThreadUsingId(Uri uri, String[] projection) {
-        return query1to1Thread(projection, getThreadIdSelection(uri), null, null);
-    }
-
-    Cursor queryGroupThread(String[] projection, String selection, String[] selectionArgs,
-            String sortOrder) {
-        SQLiteDatabase db = mSqLiteOpenHelper.getReadableDatabase();
-        return db.query(RCS_GROUP_THREAD_TABLE, projection, selection, selectionArgs, null,
-                null, sortOrder);
-    }
-
-    Cursor queryGroupThreadUsingId(Uri uri, String[] projection) {
-        return queryGroupThread(projection, getThreadIdSelection(uri), null, null);
-    }
-
-    /**
-     * @param contentValues should contain the participant ID of the other participant under key
-     *                      {@link RCS_PARTICIPANT_ID_COLUMN}
-     */
-    long insert1To1Thread(ContentValues contentValues) {
-        if (contentValues.containsKey(RCS_THREAD_ID_COLUMN)) {
-            Log.e(RcsProvider.TAG,
-                    "RcsProviderThreadHelper: inserting threads with IDs is not supported");
-            return TRANSACTION_FAILED;
-        }
-
-        Long participantId = contentValues.getAsLong(RCS_PARTICIPANT_ID_COLUMN);
-        if (participantId == null) {
-            Log.e(RcsProvider.TAG,
-                    "inserting threads without participant IDs is not supported");
-            return TRANSACTION_FAILED;
-        }
-
-        SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-        try {
-            db.beginTransaction();
-
-            if (hasExisting1To1ThreadForParticipant(db, participantId)) {
-                return TRANSACTION_FAILED;
-            }
-
-            long threadId = insertIntoCommonRcsThreads(db);
-            if (threadId == -1) {
-                return TRANSACTION_FAILED;
-            }
-
-            if (insertP2pThread(db, threadId) == -1) {
-                return TRANSACTION_FAILED;
-            }
-
-            if (insertParticipantIntoP2pThread(db, threadId, participantId) == -1) {
-                return TRANSACTION_FAILED;
-            }
-
-            db.setTransactionSuccessful();
-
-            return threadId;
-        } finally {
-            db.endTransaction();
-        }
-    }
-
-    private long insertP2pThread(SQLiteDatabase db, long threadId) {
-        ContentValues contentValues = new ContentValues(1);
-        contentValues.put(RCS_THREAD_ID_COLUMN, threadId);
-
-        return db.insert(RCS_1_TO_1_THREAD_TABLE, RCS_THREAD_ID_COLUMN, contentValues);
-    }
-
-    private long insertParticipantIntoP2pThread(
-            SQLiteDatabase db, long threadId, long participantId) {
-        ContentValues contentValues = new ContentValues(2);
-        contentValues.put(RCS_THREAD_ID_COLUMN, threadId);
-        contentValues.put(RCS_PARTICIPANT_ID_COLUMN, participantId);
-
-        return db.insert(
-                RCS_PARTICIPANT_THREAD_JUNCTION_TABLE, RCS_PARTICIPANT_ID_COLUMN, contentValues);
-    }
-
-    private boolean hasExisting1To1ThreadForParticipant(SQLiteDatabase db, long participantId) {
-        String table = joinOnColumn(
-                RCS_PARTICIPANT_THREAD_JUNCTION_TABLE,
-                RCS_1_TO_1_THREAD_TABLE,
-                RCS_THREAD_ID_COLUMN);
-
-        try (Cursor cursor = db.query(
-                table,
-                null,
-                RCS_PARTICIPANT_ID_COLUMN + "=?",
-                new String[]{Long.toString(participantId)},
-                null,
-                null,
-                null)) {
-            if (cursor == null || cursor.getCount() == 0) {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    private String joinOnColumn(String t1, String t2, String col) {
-        return t1 + " JOIN " + t2 + " ON (" + t1 + "." + col + "=" + t2 + "." + col + ")";
-    }
-
-    long insertGroupThread(ContentValues contentValues) {
-        long returnValue = TRANSACTION_FAILED;
-        if (contentValues.containsKey(RCS_THREAD_ID_COLUMN)) {
-            Log.e(RcsProvider.TAG,
-                    "RcsProviderThreadHelper: inserting threads with IDs is not supported");
-            return returnValue;
-        }
-
-        SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-        try {
-            db.beginTransaction();
-
-            // Insert into the common rcs_threads table
-            long rowId = insertIntoCommonRcsThreads(db);
-            if (rowId == INSERTION_FAILED) {
-                return returnValue;
-            }
-
-            // Add the rowId in rcs_threads table as a foreign key in rcs_group_table
-            contentValues.put(RCS_THREAD_ID_COLUMN, rowId);
-            db.insert(RCS_GROUP_THREAD_TABLE, RCS_THREAD_ID_COLUMN, contentValues);
-            contentValues.remove(RCS_THREAD_ID_COLUMN);
-
-            db.setTransactionSuccessful();
-            returnValue = rowId;
-        } finally {
-            db.endTransaction();
-        }
-        return returnValue;
-    }
-
-    private long insertIntoCommonRcsThreads(SQLiteDatabase db) {
-        return db.insert(RCS_THREAD_TABLE, RCS_THREAD_ID_COLUMN, new ContentValues());
-    }
-
-    int delete1To1Thread(String selection, String[] selectionArgs) {
-        SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-        return db.delete(RCS_1_TO_1_THREAD_TABLE, selection, selectionArgs);
-    }
-
-    int delete1To1ThreadWithId(Uri uri) {
-        return delete1To1Thread(getThreadIdSelection(uri), null);
-    }
-
-    int deleteGroupThread(String selection, String[] selectionArgs) {
-        SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-        return db.delete(RCS_GROUP_THREAD_TABLE, selection, selectionArgs);
-    }
-
-    int deleteGroupThreadWithId(Uri uri) {
-        return deleteGroupThread(getThreadIdSelection(uri), null);
-    }
-
-    int update1To1Thread(ContentValues values, String selection, String[] selectionArgs) {
-        if (values.containsKey(RCS_THREAD_ID_COLUMN)) {
-            Log.e(TAG,
-                    "RcsProviderThreadHelper: updating thread id for 1 to 1 threads is not "
-                            + "allowed");
-            return 0;
-        }
-
-        SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-        return db.update(RCS_1_TO_1_THREAD_TABLE, values, selection, selectionArgs);
-    }
-
-    int update1To1ThreadWithId(ContentValues values, Uri uri) {
-        return update1To1Thread(values, getThreadIdSelection(uri), null);
-    }
-
-    int updateGroupThread(ContentValues values, String selection, String[] selectionArgs) {
-        if (values.containsKey(RCS_THREAD_ID_COLUMN)) {
-            Log.e(TAG,
-                    "RcsProviderThreadHelper: updating thread id for group threads is not "
-                            + "allowed");
-            return 0;
-        }
-
-        SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();
-        return db.update(RCS_GROUP_THREAD_TABLE, values, selection, selectionArgs);
-    }
-
-    int updateGroupThreadWithId(ContentValues values, Uri uri) {
-        return updateGroupThread(values, getThreadIdSelection(uri), null);
-    }
-
-    private String getThreadIdSelection(Uri uri) {
-        return RCS_THREAD_ID_COLUMN + "=" + getThreadIdFromUri(uri);
-    }
-
-    static String getThreadIdFromUri(Uri uri) {
-        return uri.getPathSegments().get(THREAD_ID_INDEX_IN_URI);
-    }
-}
diff --git a/src/com/android/providers/telephony/RcsProviderUtil.java b/src/com/android/providers/telephony/RcsProviderUtil.java
deleted file mode 100644
index 38f7be1..0000000
--- a/src/com/android/providers/telephony/RcsProviderUtil.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2019 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 static android.provider.Telephony.RcsColumns.TRANSACTION_FAILED;
-
-import static android.telephony.ims.RcsQueryContinuationToken.QUERY_CONTINUATION_TOKEN;
-import static com.android.providers.telephony.RcsProvider.TAG;
-
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Parcelable;
-import android.telephony.ims.RcsQueryContinuationToken;
-import android.text.TextUtils;
-import android.util.Log;
-
-class RcsProviderUtil {
-    /**
-     * The value returned when database insertion fails,
-     * @see SQLiteDatabase#insert(String, String, ContentValues)
-     */
-    static final int INSERTION_FAILED = -1;
-
-    static void appendLimit(StringBuilder stringBuilder, int limit) {
-        if (limit > 0) {
-            stringBuilder.append(" LIMIT ").append(limit);
-        }
-    }
-
-    static void createContinuationTokenBundle(Cursor cursor, Parcelable continuationToken,
-            String tokenKey) {
-        if (cursor.getCount() > 0) {
-            Bundle bundle = new Bundle();
-            bundle.putParcelable(tokenKey, continuationToken);
-            cursor.setExtras(bundle);
-        }
-    }
-
-    /**
-     * This method gets a token with raw query, performs the query, increments the token's offset
-     * and returns it as a cursor extra
-     */
-    static Cursor performContinuationQuery(SQLiteDatabase db,
-            RcsQueryContinuationToken continuationToken) {
-        String rawQuery = continuationToken.getRawQuery();
-        int offset = continuationToken.getOffset();
-
-        if (offset <= 0 || TextUtils.isEmpty(rawQuery)) {
-            Log.e(TAG, "RcsProviderUtil: Invalid continuation token");
-            return null;
-        }
-
-        String continuationQuery = rawQuery + " OFFSET " + offset;
-
-        Cursor cursor = db.rawQuery(continuationQuery, null);
-        if (cursor.getCount() > 0) {
-            continuationToken.incrementOffset();
-            Bundle bundle = new Bundle();
-            bundle.putParcelable(QUERY_CONTINUATION_TOKEN, continuationToken);
-            cursor.setExtras(bundle);
-        }
-
-        return cursor;
-    }
-
-    static Uri buildUriWithRowIdAppended(Uri prefix, long rowId) {
-        if (rowId == TRANSACTION_FAILED) {
-            return null;
-        }
-        return Uri.withAppendedPath(prefix, Long.toString(rowId));
-    }
-
-    static Uri returnUriAsIsIfSuccessful(Uri uri, long rowId) {
-        if (rowId == TRANSACTION_FAILED) {
-            return null;
-        }
-        return uri;
-    }
-}
diff --git a/src/com/android/providers/telephony/ServiceStateProvider.java b/src/com/android/providers/telephony/ServiceStateProvider.java
deleted file mode 100644
index afd8fa1..0000000
--- a/src/com/android/providers/telephony/ServiceStateProvider.java
+++ /dev/null
@@ -1,353 +0,0 @@
-/* //device/content/providers/telephony/TelephonyProvider.java
-**
-** Copyright 2016, 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 static android.provider.Telephony.ServiceStateTable;
-import static android.provider.Telephony.ServiceStateTable.CDMA_DEFAULT_ROAMING_INDICATOR;
-import static android.provider.Telephony.ServiceStateTable.CDMA_ERI_ICON_INDEX;
-import static android.provider.Telephony.ServiceStateTable.CDMA_ERI_ICON_MODE;
-import static android.provider.Telephony.ServiceStateTable.CDMA_ROAMING_INDICATOR;
-import static android.provider.Telephony.ServiceStateTable.CONTENT_URI;
-import static android.provider.Telephony.ServiceStateTable.CSS_INDICATOR;
-import static android.provider.Telephony.ServiceStateTable.DATA_OPERATOR_ALPHA_LONG;
-import static android.provider.Telephony.ServiceStateTable.DATA_OPERATOR_ALPHA_SHORT;
-import static android.provider.Telephony.ServiceStateTable.DATA_OPERATOR_NUMERIC;
-import static android.provider.Telephony.ServiceStateTable.DATA_REG_STATE;
-import static android.provider.Telephony.ServiceStateTable.DATA_ROAMING_TYPE;
-import static android.provider.Telephony.ServiceStateTable.IS_EMERGENCY_ONLY;
-import static android.provider.Telephony.ServiceStateTable.IS_MANUAL_NETWORK_SELECTION;
-import static android.provider.Telephony.ServiceStateTable.IS_USING_CARRIER_AGGREGATION;
-import static android.provider.Telephony.ServiceStateTable.NETWORK_ID;
-import static android.provider.Telephony.ServiceStateTable.OPERATOR_ALPHA_LONG_RAW;
-import static android.provider.Telephony.ServiceStateTable.OPERATOR_ALPHA_SHORT_RAW;
-import static android.provider.Telephony.ServiceStateTable.RIL_DATA_RADIO_TECHNOLOGY;
-import static android.provider.Telephony.ServiceStateTable.RIL_VOICE_RADIO_TECHNOLOGY;
-import static android.provider.Telephony.ServiceStateTable.SERVICE_STATE;
-import static android.provider.Telephony.ServiceStateTable.SYSTEM_ID;
-import static android.provider.Telephony.ServiceStateTable.VOICE_OPERATOR_ALPHA_LONG;
-import static android.provider.Telephony.ServiceStateTable.VOICE_OPERATOR_ALPHA_SHORT;
-import static android.provider.Telephony.ServiceStateTable.VOICE_OPERATOR_NUMERIC;
-import static android.provider.Telephony.ServiceStateTable.VOICE_REG_STATE;
-import static android.provider.Telephony.ServiceStateTable.VOICE_ROAMING_TYPE;
-import static android.provider.Telephony.ServiceStateTable.getUriForSubscriptionId;
-import static android.provider.Telephony.ServiceStateTable.getUriForSubscriptionIdAndField;
-
-import android.content.ContentProvider;
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.database.MatrixCursor;
-import android.database.MatrixCursor.RowBuilder;
-import android.net.Uri;
-import android.os.Parcel;
-import android.telephony.ServiceState;
-import android.telephony.SubscriptionManager;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.telephony.SubscriptionController;
-
-import java.util.HashMap;
-
-
-public class ServiceStateProvider extends ContentProvider {
-    private static final String TAG = "ServiceStateProvider";
-
-    public static final String AUTHORITY = ServiceStateTable.AUTHORITY;
-    public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY);
-
-    private final HashMap<Integer, ServiceState> mServiceStates = new HashMap<>();
-    private static final String[] sColumns = {
-        VOICE_REG_STATE,
-        DATA_REG_STATE,
-        VOICE_ROAMING_TYPE,
-        DATA_ROAMING_TYPE,
-        VOICE_OPERATOR_ALPHA_LONG,
-        VOICE_OPERATOR_ALPHA_SHORT,
-        VOICE_OPERATOR_NUMERIC,
-        DATA_OPERATOR_ALPHA_LONG,
-        DATA_OPERATOR_ALPHA_SHORT,
-        DATA_OPERATOR_NUMERIC,
-        IS_MANUAL_NETWORK_SELECTION,
-        RIL_VOICE_RADIO_TECHNOLOGY,
-        RIL_DATA_RADIO_TECHNOLOGY,
-        CSS_INDICATOR,
-        NETWORK_ID,
-        SYSTEM_ID,
-        CDMA_ROAMING_INDICATOR,
-        CDMA_DEFAULT_ROAMING_INDICATOR,
-        CDMA_ERI_ICON_INDEX,
-        CDMA_ERI_ICON_MODE,
-        IS_EMERGENCY_ONLY,
-        IS_USING_CARRIER_AGGREGATION,
-        OPERATOR_ALPHA_LONG_RAW,
-        OPERATOR_ALPHA_SHORT_RAW,
-    };
-
-    @Override
-    public boolean onCreate() {
-        return true;
-    }
-
-    @VisibleForTesting
-    public ServiceState getServiceState(int subId) {
-        return mServiceStates.get(subId);
-    }
-
-    @VisibleForTesting
-    public int getDefaultSubId() {
-        return SubscriptionController.getInstance().getDefaultSubId();
-    }
-
-    @Override
-    public Uri insert(Uri uri, ContentValues values) {
-        if (uri.isPathPrefixMatch(CONTENT_URI)) {
-            // Parse the subId
-            int subId = 0;
-            try {
-                subId = Integer.parseInt(uri.getLastPathSegment());
-            } catch (NumberFormatException e) {
-                Log.e(TAG, "insert: no subId provided in uri");
-                throw e;
-            }
-            Log.d(TAG, "subId=" + subId);
-
-            // handle DEFAULT_SUBSCRIPTION_ID
-            if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
-                subId = getDefaultSubId();
-            }
-
-            final Parcel p = Parcel.obtain();
-            final byte[] rawBytes = values.getAsByteArray(SERVICE_STATE);
-            p.unmarshall(rawBytes, 0, rawBytes.length);
-            p.setDataPosition(0);
-
-            // create the new service state
-            final ServiceState newSS = ServiceState.CREATOR.createFromParcel(p);
-
-            // notify listeners
-            // if ss is null (e.g. first service state update) we will notify for all fields
-            ServiceState ss = getServiceState(subId);
-            notifyChangeForSubIdAndField(getContext(), ss, newSS, subId);
-            notifyChangeForSubId(getContext(), ss, newSS, subId);
-
-            // store the new service state
-            mServiceStates.put(subId, newSS);
-            return uri;
-        }
-        return null;
-    }
-
-    @Override
-    public int delete(Uri uri, String selection, String[] selectionArgs) {
-        throw new RuntimeException("Not supported");
-    }
-
-    @Override
-    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
-        throw new RuntimeException("Not supported");
-    }
-
-    @Override
-    public String getType(Uri uri) {
-        throw new RuntimeException("Not supported");
-    }
-
-    @Override
-    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
-            String sortOrder) {
-        if (!uri.isPathPrefixMatch(CONTENT_URI)) {
-            throw new IllegalArgumentException("Invalid URI: " + uri);
-        } else {
-            // Parse the subId
-            int subId = 0;
-            try {
-                subId = Integer.parseInt(uri.getLastPathSegment());
-            } catch (NumberFormatException e) {
-                Log.d(TAG, "query: no subId provided in uri, using default.");
-                subId = getDefaultSubId();
-            }
-            Log.d(TAG, "subId=" + subId);
-
-            // handle DEFAULT_SUBSCRIPTION_ID
-            if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
-                subId = getDefaultSubId();
-            }
-
-            // Get the service state
-            ServiceState ss = getServiceState(subId);
-            if (ss == null) {
-                Log.d(TAG, "returning null");
-                return null;
-            }
-
-            // Build the result
-            final int voice_reg_state = ss.getVoiceRegState();
-            final int data_reg_state = ss.getDataRegState();
-            final int voice_roaming_type = ss.getVoiceRoamingType();
-            final int data_roaming_type = ss.getDataRoamingType();
-            final String voice_operator_alpha_long = ss.getVoiceOperatorAlphaLong();
-            final String voice_operator_alpha_short = ss.getVoiceOperatorAlphaShort();
-            final String voice_operator_numeric = ss.getVoiceOperatorNumeric();
-            final String data_operator_alpha_long = ss.getDataOperatorAlphaLong();
-            final String data_operator_alpha_short = ss.getDataOperatorAlphaShort();
-            final String data_operator_numeric = ss.getDataOperatorNumeric();
-            final int is_manual_network_selection = (ss.getIsManualSelection()) ? 1 : 0;
-            final int ril_voice_radio_technology = ss.getRilVoiceRadioTechnology();
-            final int ril_data_radio_technology = ss.getRilDataRadioTechnology();
-            final int css_indicator = ss.getCssIndicator();
-            final int network_id = ss.getCdmaNetworkId();
-            final int system_id = ss.getCdmaSystemId();
-            final int cdma_roaming_indicator = ss.getCdmaRoamingIndicator();
-            final int cdma_default_roaming_indicator = ss.getCdmaDefaultRoamingIndicator();
-            final int cdma_eri_icon_index = ss.getCdmaEriIconIndex();
-            final int cdma_eri_icon_mode = ss.getCdmaEriIconMode();
-            final int is_emergency_only = (ss.isEmergencyOnly()) ? 1 : 0;
-            final int is_using_carrier_aggregation = (ss.isUsingCarrierAggregation()) ? 1 : 0;
-            final String operator_alpha_long_raw = ss.getOperatorAlphaLongRaw();
-            final String operator_alpha_short_raw = ss.getOperatorAlphaShortRaw();
-
-            return buildSingleRowResult(projection, sColumns, new Object[] {
-                        voice_reg_state,
-                        data_reg_state,
-                        voice_roaming_type,
-                        data_roaming_type,
-                        voice_operator_alpha_long,
-                        voice_operator_alpha_short,
-                        voice_operator_numeric,
-                        data_operator_alpha_long,
-                        data_operator_alpha_short,
-                        data_operator_numeric,
-                        is_manual_network_selection,
-                        ril_voice_radio_technology,
-                        ril_data_radio_technology,
-                        css_indicator,
-                        network_id,
-                        system_id,
-                        cdma_roaming_indicator,
-                        cdma_default_roaming_indicator,
-                        cdma_eri_icon_index,
-                        cdma_eri_icon_mode,
-                        is_emergency_only,
-                        is_using_carrier_aggregation,
-                        operator_alpha_long_raw,
-                        operator_alpha_short_raw,
-            });
-        }
-    }
-
-    private static Cursor buildSingleRowResult(String[] projection, String[] availableColumns,
-            Object[] data) {
-        if (projection == null) {
-            projection = availableColumns;
-        }
-        final MatrixCursor c = new MatrixCursor(projection, 1);
-        final RowBuilder row = c.newRow();
-        for (int i = 0; i < c.getColumnCount(); i++) {
-            final String columnName = c.getColumnName(i);
-            boolean found = false;
-            for (int j = 0; j < availableColumns.length; j++) {
-                if (availableColumns[j].equals(columnName)) {
-                    row.add(data[j]);
-                    found = true;
-                    break;
-                }
-            }
-            if (!found) {
-                throw new IllegalArgumentException("Invalid column " + projection[i]);
-            }
-        }
-        return c;
-    }
-
-    /**
-     * Notify interested apps that certain fields of the ServiceState have changed.
-     *
-     * Apps which want to wake when specific fields change can use
-     * JobScheduler's TriggerContentUri.  This replaces the waking functionality of the implicit
-     * broadcast of ACTION_SERVICE_STATE_CHANGED for apps targetting version O.
-     *
-     * We will only notify for certain fields. This is an intentional change from the behavior of
-     * the broadcast. Listeners will be notified when the voice or data registration state or
-     * roaming type changes.
-     */
-    @VisibleForTesting
-    public static void notifyChangeForSubIdAndField(Context context, ServiceState oldSS,
-            ServiceState newSS, int subId) {
-        final boolean firstUpdate = (oldSS == null) ? true : false;
-
-        // for every field, if the field has changed values, notify via the provider
-        if (firstUpdate || voiceRegStateChanged(oldSS, newSS)) {
-            context.getContentResolver().notifyChange(
-                    getUriForSubscriptionIdAndField(subId, VOICE_REG_STATE),
-                    /* observer= */ null, /* syncToNetwork= */ false);
-        }
-        if (firstUpdate || dataRegStateChanged(oldSS, newSS)) {
-            context.getContentResolver().notifyChange(
-                    getUriForSubscriptionIdAndField(subId, DATA_REG_STATE), null, false);
-        }
-        if (firstUpdate || voiceRoamingTypeChanged(oldSS, newSS)) {
-            context.getContentResolver().notifyChange(
-                    getUriForSubscriptionIdAndField(subId, VOICE_ROAMING_TYPE), null, false);
-        }
-        if (firstUpdate || dataRoamingTypeChanged(oldSS, newSS)) {
-            context.getContentResolver().notifyChange(
-                    getUriForSubscriptionIdAndField(subId, DATA_ROAMING_TYPE), null, false);
-        }
-    }
-
-    private static boolean voiceRegStateChanged(ServiceState oldSS, ServiceState newSS) {
-        return oldSS.getVoiceRegState() != newSS.getVoiceRegState();
-    }
-
-    private static boolean dataRegStateChanged(ServiceState oldSS, ServiceState newSS) {
-        return oldSS.getDataRegState() != newSS.getDataRegState();
-    }
-
-    private static boolean voiceRoamingTypeChanged(ServiceState oldSS, ServiceState newSS) {
-        return oldSS.getVoiceRoamingType() != newSS.getVoiceRoamingType();
-    }
-
-    private static boolean dataRoamingTypeChanged(ServiceState oldSS, ServiceState newSS) {
-        return oldSS.getDataRoamingType() != newSS.getDataRoamingType();
-    }
-
-    /**
-     * Notify interested apps that the ServiceState has changed.
-     *
-     * Apps which want to wake when any field in the ServiceState has changed can use
-     * JobScheduler's TriggerContentUri.  This replaces the waking functionality of the implicit
-     * broadcast of ACTION_SERVICE_STATE_CHANGED for apps targeting version O.
-     *
-     * We will only notify for certain fields. This is an intentional change from the behavior of
-     * the broadcast. Listeners will only be notified when the voice/data registration state or
-     * roaming type changes.
-     */
-    @VisibleForTesting
-    public static void notifyChangeForSubId(Context context, ServiceState oldSS, ServiceState newSS,
-            int subId) {
-        // if the voice or data registration or roaming state field has changed values, notify via
-        // the provider.
-        // If oldSS is null and newSS is not (e.g. first update of service state) this will also
-        // notify
-        if (oldSS == null || voiceRegStateChanged(oldSS, newSS) || dataRegStateChanged(oldSS, newSS)
-                || voiceRoamingTypeChanged(oldSS, newSS) || dataRoamingTypeChanged(oldSS, newSS)) {
-            context.getContentResolver().notifyChange(getUriForSubscriptionId(subId), null, false);
-        }
-    }
-}
diff --git a/src/com/android/providers/telephony/SmsProvider.java b/src/com/android/providers/telephony/SmsProvider.java
index 1213c37..81f732b 100644
--- a/src/com/android/providers/telephony/SmsProvider.java
+++ b/src/com/android/providers/telephony/SmsProvider.java
@@ -36,21 +36,25 @@
 import android.provider.Telephony;
 import android.provider.Telephony.MmsSms;
 import android.provider.Telephony.Sms;
-import android.provider.Telephony.TextBasedSmsColumns;
 import android.provider.Telephony.Threads;
 import android.telephony.SmsManager;
 import android.telephony.SmsMessage;
+import android.telephony.SubscriptionManager;
 import android.text.TextUtils;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
 
-import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 
 public class SmsProvider extends ContentProvider {
+    /* No response constant from SmsResponse */
+    static final int NO_ERROR_CODE = -1;
+
     private static final Uri NOTIFICATION_URI = Uri.parse("content://sms");
     private static final Uri ICC_URI = Uri.parse("content://sms/icc");
+    private static final Uri ICC_SUBID_URI = Uri.parse("content://sms/icc_subId");
     static final String TABLE_SMS = "sms";
     static final String TABLE_RAW = "raw";
     private static final String TABLE_SR_PENDING = "sr_pending";
@@ -75,7 +79,7 @@
         // N.B.: These columns must appear in the same order as the
         // calls to add appear in convertIccToSms.
         "service_center_address",       // getServiceCenterAddress
-        "address",                      // getDisplayOriginatingAddress
+        "address",                      // getDisplayOriginatingAddress or getRecipientAddress
         "message_class",                // getMessageClass
         "body",                         // getDisplayMessageBody
         "date",                         // getTimestampMillis
@@ -83,9 +87,9 @@
         "index_on_icc",                 // getIndexOnIcc
         "is_status_report",             // isStatusReportMessage
         "transport_type",               // Always "sms".
-        "type",                         // Always MESSAGE_TYPE_ALL.
+        "type",                         // depend on getStatusOnIcc
         "locked",                       // Always 0 (false).
-        "error_code",                   // Always 0
+        "error_code",                   // Always -1 (NO_ERROR_CODE), previously it was 0 always.
         "_id"
     };
 
@@ -255,12 +259,45 @@
                 break;
 
             case SMS_ALL_ICC:
-                return getAllMessagesFromIcc();
+            case SMS_ALL_ICC_SUBID:
+                {
+                    int subId;
+                    if (match == SMS_ALL_ICC) {
+                        subId = SmsManager.getDefaultSmsSubscriptionId();
+                    } else {
+                        try {
+                            subId = Integer.parseInt(url.getPathSegments().get(1));
+                        } catch (NumberFormatException e) {
+                            throw new IllegalArgumentException("Wrong path segements, uri= " + url);
+                        }
+                    }
+                    Cursor ret = getAllMessagesFromIcc(subId);
+                    ret.setNotificationUri(getContext().getContentResolver(),
+                            match == SMS_ALL_ICC ? ICC_URI : ICC_SUBID_URI);
+                    return ret;
+                }
 
             case SMS_ICC:
-                String messageIndexString = url.getPathSegments().get(1);
-
-                return getSingleMessageFromIcc(messageIndexString);
+            case SMS_ICC_SUBID:
+                {
+                    int subId;
+                    int messageIndex;
+                    try {
+                        if (match == SMS_ICC) {
+                            subId = SmsManager.getDefaultSmsSubscriptionId();
+                            messageIndex = Integer.parseInt(url.getPathSegments().get(1));
+                        } else {
+                            subId = Integer.parseInt(url.getPathSegments().get(1));
+                            messageIndex = Integer.parseInt(url.getPathSegments().get(2));
+                        }
+                    } catch (NumberFormatException e) {
+                        throw new IllegalArgumentException("Wrong path segements, uri= " + url);
+                    }
+                    Cursor ret = getSingleMessageFromIcc(subId, messageIndex);
+                    ret.setNotificationUri(getContext().getContentResolver(),
+                            match == SMS_ICC ? ICC_URI : ICC_SUBID_URI);
+                    return ret;
+                }
 
             default:
                 Log.e(TAG, "Invalid request: " + url);
@@ -302,68 +339,92 @@
     }
 
     private Object[] convertIccToSms(SmsMessage message, int id) {
+        int statusOnIcc = message.getStatusOnIcc();
+        int type = Sms.MESSAGE_TYPE_ALL;
+        switch (statusOnIcc) {
+            case SmsManager.STATUS_ON_ICC_READ:
+            case SmsManager.STATUS_ON_ICC_UNREAD:
+                type = Sms.MESSAGE_TYPE_INBOX;
+                break;
+            case SmsManager.STATUS_ON_ICC_SENT:
+                type = Sms.MESSAGE_TYPE_SENT;
+                break;
+            case SmsManager.STATUS_ON_ICC_UNSENT:
+                type = Sms.MESSAGE_TYPE_OUTBOX;
+                break;
+        }
         // N.B.: These calls must appear in the same order as the
         // columns appear in ICC_COLUMNS.
         Object[] row = new Object[13];
         row[0] = message.getServiceCenterAddress();
-        row[1] = message.getDisplayOriginatingAddress();
+        row[1] =
+                (type == Sms.MESSAGE_TYPE_INBOX)
+                        ? message.getDisplayOriginatingAddress()
+                        : message.getRecipientAddress();
+
         row[2] = String.valueOf(message.getMessageClass());
         row[3] = message.getDisplayMessageBody();
         row[4] = message.getTimestampMillis();
-        row[5] = Sms.STATUS_NONE;
+        row[5] = statusOnIcc;
         row[6] = message.getIndexOnIcc();
         row[7] = message.isStatusReportMessage();
         row[8] = "sms";
-        row[9] = TextBasedSmsColumns.MESSAGE_TYPE_ALL;
+        row[9] = type;
         row[10] = 0;      // locked
-        row[11] = 0;      // error_code
+        row[11] = NO_ERROR_CODE;
         row[12] = id;
         return row;
     }
 
     /**
-     * Return a Cursor containing just one message from the ICC.
+     * Gets single message from the ICC for a subscription ID.
+     *
+     * @param subId the subscription ID.
+     * @param messageIndex the message index of the messaage in the ICC.
+     * @return a cursor containing just one message from the ICC for the subscription ID.
      */
-    private Cursor getSingleMessageFromIcc(String messageIndexString) {
-        int messageIndex = -1;
-        try {
-            messageIndex = Integer.parseInt(messageIndexString);
-        } catch (NumberFormatException exception) {
-            throw new IllegalArgumentException("Bad SMS ICC ID: " + messageIndexString);
+    private Cursor getSingleMessageFromIcc(int subId, int messageIndex) {
+        if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+            throw new IllegalArgumentException("Invalid Subscription ID " + subId);
         }
-        ArrayList<SmsMessage> messages;
-        final SmsManager smsManager = SmsManager.getDefault();
-        // Use phone id to avoid AppOps uid mismatch in telephony
+        SmsManager smsManager = SmsManager.getSmsManagerForSubscriptionId(subId);
+        List<SmsMessage> messages;
+
+        // Use phone app permissions to avoid UID mismatch in AppOpsManager.noteOp() call.
         long token = Binder.clearCallingIdentity();
         try {
-            messages = smsManager.getAllMessagesFromIcc();
+            messages = smsManager.getMessagesFromIcc();
         } finally {
             Binder.restoreCallingIdentity(token);
         }
-        if (messages == null) {
-            throw new IllegalArgumentException("ICC message not retrieved");
-        }
+
         final SmsMessage message = messages.get(messageIndex);
         if (message == null) {
             throw new IllegalArgumentException(
-                    "Message not retrieved. ID: " + messageIndexString);
+                    "No message in index " + messageIndex + " for subId " + subId);
         }
         MatrixCursor cursor = new MatrixCursor(ICC_COLUMNS, 1);
         cursor.addRow(convertIccToSms(message, 0));
-        return withIccNotificationUri(cursor);
+        return cursor;
     }
 
     /**
-     * Return a Cursor listing all the messages stored on the ICC.
+     * Gets all the messages in the ICC for a subscription ID.
+     *
+     * @param subId the subscription ID.
+     * @return a cursor listing all the message in the ICC for the subscription ID.
      */
-    private Cursor getAllMessagesFromIcc() {
-        SmsManager smsManager = SmsManager.getDefault();
-        ArrayList<SmsMessage> messages;
+    private Cursor getAllMessagesFromIcc(int subId) {
+        if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+            throw new IllegalArgumentException("Invalid Subscription ID " + subId);
+        }
+        SmsManager smsManager = SmsManager.getSmsManagerForSubscriptionId(subId);
+        List<SmsMessage> messages;
 
-        // use phone app permissions to avoid UID mismatch in AppOpsManager.noteOp() call
+        // Use phone app permissions to avoid UID mismatch in AppOpsManager.noteOp() call
         long token = Binder.clearCallingIdentity();
         try {
-            messages = smsManager.getAllMessagesFromIcc();
+            messages = smsManager.getMessagesFromIcc();
         } finally {
             Binder.restoreCallingIdentity(token);
         }
@@ -376,11 +437,6 @@
                 cursor.addRow(convertIccToSms(message, i));
             }
         }
-        return withIccNotificationUri(cursor);
-    }
-
-    private Cursor withIccNotificationUri(Cursor cursor) {
-        cursor.setNotificationUri(getContext().getContentResolver(), ICC_URI);
         return cursor;
     }
 
@@ -456,11 +512,16 @@
         try {
             Uri insertUri = insertInner(url, initialValues, callerUid, callerPkg);
 
-            // The raw table is used by the telephony layer for storing an sms before
-            // sending out a notification that an sms has arrived. We don't want to notify
-            // the default sms app of changes to this table.
-            final boolean notifyIfNotDefault = sURLMatcher.match(url) != SMS_RAW_MESSAGE;
-            notifyChange(notifyIfNotDefault, insertUri, callerPkg);
+            int match = sURLMatcher.match(url);
+            // Skip notifyChange() if insertUri is null for SMS_ALL_ICC or SMS_ALL_ICC_SUBID caused
+            // by failure of insertMessageToIcc()(e.g. SIM full).
+            if (insertUri != null || (match != SMS_ALL_ICC && match != SMS_ALL_ICC_SUBID)) {
+                // The raw table is used by the telephony layer for storing an sms before sending
+                // out a notification that an sms has arrived. We don't want to notify the default
+                // sms app of changes to this table.
+                final boolean notifyIfNotDefault = match != SMS_RAW_MESSAGE;
+                notifyChange(notifyIfNotDefault, insertUri, callerPkg);
+            }
             return insertUri;
         } finally {
             Binder.restoreCallingIdentity(token);
@@ -526,6 +587,47 @@
                 table = "canonical_addresses";
                 break;
 
+            case SMS_ALL_ICC:
+            case SMS_ALL_ICC_SUBID:
+                int subId;
+                if (match == SMS_ALL_ICC) {
+                    subId = SmsManager.getDefaultSmsSubscriptionId();
+                } else {
+                    try {
+                        subId = Integer.parseInt(url.getPathSegments().get(1));
+                    } catch (NumberFormatException e) {
+                        throw new IllegalArgumentException(
+                                "Wrong path segements for SMS_ALL_ICC_SUBID, uri= " + url);
+                    }
+                }
+
+                if (initialValues == null) {
+                    throw new IllegalArgumentException("ContentValues is null");
+                }
+
+                String scAddress = initialValues.getAsString(Sms.SERVICE_CENTER);
+                String address = initialValues.getAsString(Sms.ADDRESS);
+                String message = initialValues.getAsString(Sms.BODY);
+                boolean isRead = true;
+                Integer obj = initialValues.getAsInteger(Sms.TYPE);
+
+                if (obj == null || address == null || message == null) {
+                    throw new IllegalArgumentException("Missing SMS data");
+                }
+
+                type = obj.intValue();
+                if (!isSupportedType(type)) {
+                    throw new IllegalArgumentException("Unsupported message type= " + type);
+                }
+                obj = initialValues.getAsInteger(Sms.READ); // 0: Unread, 1: Read
+                if (obj != null && obj.intValue() == 0) {
+                    isRead = false;
+                }
+
+                Long date = initialValues.getAsLong(Sms.DATE);
+                return insertMessageToIcc(subId, scAddress, address, message, type, isRead,
+                        date != null ? date : 0) ? url : null;
+
             default:
                 Log.e(TAG, "Invalid request: " + url);
                 return null;
@@ -642,7 +744,12 @@
             db.insert(TABLE_WORDS, Telephony.MmsSms.WordsTable.INDEXED_TEXT, cv);
         }
         if (rowID > 0) {
-            Uri uri = Uri.withAppendedPath(url, String.valueOf(rowID));
+            Uri uri = null;
+            if (table == TABLE_SMS) {
+                uri = Uri.withAppendedPath(Sms.CONTENT_URI, String.valueOf(rowID));
+            } else {
+                uri = Uri.withAppendedPath(url, String.valueOf(rowID));
+            }
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
                 Log.d(TAG, "insert " + uri + " succeeded");
             }
@@ -654,6 +761,63 @@
         return null;
     }
 
+    private boolean isSupportedType(int messageType) {
+        return (messageType == Sms.MESSAGE_TYPE_INBOX)
+                || (messageType == Sms.MESSAGE_TYPE_OUTBOX)
+                || (messageType == Sms.MESSAGE_TYPE_SENT);
+    }
+
+    private int getMessageStatusForIcc(int messageType, boolean isRead) {
+        if (messageType == Sms.MESSAGE_TYPE_SENT) {
+            return SmsManager.STATUS_ON_ICC_SENT;
+        } else if (messageType == Sms.MESSAGE_TYPE_OUTBOX) {
+            return SmsManager.STATUS_ON_ICC_UNSENT;
+        } else { // Sms.MESSAGE_BOX_INBOX
+            if (isRead) {
+                return SmsManager.STATUS_ON_ICC_READ;
+            } else {
+                return SmsManager.STATUS_ON_ICC_UNREAD;
+            }
+        }
+    }
+
+    /**
+     * Inserts new message to the ICC for a subscription ID.
+     *
+     * @param subId the subscription ID.
+     * @param scAddress the SMSC for this message.
+     * @param address destination or originating address.
+     * @param message the message text.
+     * @param messageType type of the message.
+     * @param isRead ture if the message has been read. Otherwise false.
+     * @param date the date the message was received.
+     * @return true for succeess. Otherwise false.
+     */
+    private boolean insertMessageToIcc(int subId, String scAddress, String address, String message,
+            int messageType, boolean isRead, long date) {
+        if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+            throw new IllegalArgumentException("Invalid Subscription ID " + subId);
+        }
+        SmsManager smsManager = SmsManager.getSmsManagerForSubscriptionId(subId);
+
+        int status = getMessageStatusForIcc(messageType, isRead);
+        SmsMessage.SubmitPdu smsPdu =
+                SmsMessage.getSmsPdu(subId, status, scAddress, address, message, date);
+
+        if (smsPdu == null) {
+            throw new IllegalArgumentException("Failed to create SMS PDU");
+        }
+
+        // Use phone app permissions to avoid UID mismatch in AppOpsManager.noteOp() call.
+        long token = Binder.clearCallingIdentity();
+        try {
+            return smsManager.copyMessageToIcc(
+                    smsPdu.encodedScAddress, smsPdu.encodedMessage, status);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
     @Override
     public int delete(Uri url, String where, String[] whereArgs) {
         int count;
@@ -719,9 +883,30 @@
                 break;
 
             case SMS_ICC:
-                String messageIndexString = url.getPathSegments().get(1);
-
-                return deleteMessageFromIcc(messageIndexString);
+            case SMS_ICC_SUBID:
+                int subId;
+                int messageIndex;
+                boolean success;
+                try {
+                    if (match == SMS_ICC) {
+                        subId = SmsManager.getDefaultSmsSubscriptionId();
+                        messageIndex = Integer.parseInt(url.getPathSegments().get(1));
+                    } else {
+                        subId = Integer.parseInt(url.getPathSegments().get(1));
+                        messageIndex = Integer.parseInt(url.getPathSegments().get(2));
+                    }
+                } catch (NumberFormatException e) {
+                    throw new IllegalArgumentException("Wrong path segements, uri= " + url);
+                }
+                success = deleteMessageFromIcc(subId, messageIndex);
+                // Notify changes even failure case since there might be some changes should be
+                // known.
+                getContext().getContentResolver().notifyChange(
+                        match == SMS_ICC ? ICC_URI : ICC_SUBID_URI,
+                        null,
+                        true,
+                        UserHandle.USER_ALL);
+                return success ? 1 : 0; // return deleted count
 
             default:
                 throw new IllegalArgumentException("Unknown URL");
@@ -734,24 +919,23 @@
     }
 
     /**
-     * Delete the message at index from ICC.  Return true iff
-     * successful.
+     * Deletes the message at index from the ICC for a subscription ID.
+     *
+     * @param subId the subscription ID.
+     * @param messageIndex the message index of the message in the ICC.
+     * @return true for succeess. Otherwise false.
      */
-    private int deleteMessageFromIcc(String messageIndexString) {
-        SmsManager smsManager = SmsManager.getDefault();
-        // Use phone id to avoid AppOps uid mismatch in telephony
+    private boolean deleteMessageFromIcc(int subId, int messageIndex) {
+        if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+            throw new IllegalArgumentException("Invalid Subscription ID " + subId);
+        }
+        SmsManager smsManager = SmsManager.getSmsManagerForSubscriptionId(subId);
+
+        // Use phone app permissions to avoid UID mismatch in AppOpsManager.noteOp() call.
         long token = Binder.clearCallingIdentity();
         try {
-            return smsManager.deleteMessageFromIcc(
-                    Integer.parseInt(messageIndexString))
-                    ? 1 : 0;
-        } catch (NumberFormatException exception) {
-            throw new IllegalArgumentException(
-                    "Bad SMS ICC ID: " + messageIndexString);
+            return smsManager.deleteMessageFromIcc(messageIndex);
         } finally {
-            ContentResolver cr = getContext().getContentResolver();
-            cr.notifyChange(ICC_URI, null, true, UserHandle.USER_ALL);
-
             Binder.restoreCallingIdentity(token);
         }
     }
@@ -895,6 +1079,8 @@
     private static final int SMS_QUEUED = 26;
     private static final int SMS_UNDELIVERED = 27;
     private static final int SMS_RAW_MESSAGE_PERMANENT_DELETE = 28;
+    private static final int SMS_ALL_ICC_SUBID = 29;
+    private static final int SMS_ICC_SUBID = 30;
 
     private static final UriMatcher sURLMatcher =
             new UriMatcher(UriMatcher.NO_MATCH);
@@ -926,6 +1112,8 @@
         sURLMatcher.addURI("sms", "sr_pending", SMS_STATUS_PENDING);
         sURLMatcher.addURI("sms", "icc", SMS_ALL_ICC);
         sURLMatcher.addURI("sms", "icc/#", SMS_ICC);
+        sURLMatcher.addURI("sms", "icc_subId/#", SMS_ALL_ICC_SUBID);
+        sURLMatcher.addURI("sms", "icc_subId/#/#", SMS_ICC_SUBID);
         //we keep these for not breaking old applications
         sURLMatcher.addURI("sms", "sim", SMS_ALL_ICC);
         sURLMatcher.addURI("sms", "sim/#", SMS_ICC);
diff --git a/src/com/android/providers/telephony/SqlTokenFinder.java b/src/com/android/providers/telephony/SqlTokenFinder.java
deleted file mode 100644
index 9be49fe..0000000
--- a/src/com/android/providers/telephony/SqlTokenFinder.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (C) 2019 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.annotation.Nullable;
-
-import java.util.function.Consumer;
-
-/**
- * Simple SQL parser to check statements for usage of prohibited/sensitive fields. Mostly copied
- * from
- * packages/providers/ContactsProvider/src/com/android/providers/contacts/sqlite/SqlChecker.java
- */
-public class SqlTokenFinder{
-    private static boolean isAlpha(char ch) {
-        return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || (ch == '_');
-    }
-
-    private static boolean isNum(char ch) {
-        return ('0' <= ch && ch <= '9');
-    }
-
-    private static boolean isAlNum(char ch) {
-        return isAlpha(ch) || isNum(ch);
-    }
-
-    private static boolean isAnyOf(char ch, String set) {
-        return set.indexOf(ch) >= 0;
-    }
-
-    private static char peek(String s, int index) {
-        return index < s.length() ? s.charAt(index) : '\0';
-    }
-
-    /**
-     * SQL Tokenizer specialized to extract tokens from SQL (snippets).
-     *
-     * Based on sqlite3GetToken() in tokenzie.c in SQLite.
-     *
-     * Source for v3.8.6 (which android uses): http://www.sqlite.org/src/artifact/ae45399d6252b4d7
-     * (Latest source as of now: http://www.sqlite.org/src/artifact/78c8085bc7af1922)
-     *
-     * Also draft spec: http://www.sqlite.org/draft/tokenreq.html
-     */
-    public static void findTokens(@Nullable String sql, Consumer<String> checker) {
-        if (sql == null) {
-            return;
-        }
-        int pos = 0;
-        final int len = sql.length();
-        while (pos < len) {
-            final char ch = peek(sql, pos);
-
-            // Regular token.
-            if (isAlpha(ch)) {
-                final int start = pos;
-                pos++;
-                while (isAlNum(peek(sql, pos))) {
-                    pos++;
-                }
-                final int end = pos;
-
-                final String token = sql.substring(start, end);
-                checker.accept(token);
-
-                continue;
-            }
-
-            // Handle quoted tokens
-            if (isAnyOf(ch, "'\"`")) {
-                final int quoteStart = pos;
-                pos++;
-
-                for (;;) {
-                    pos = sql.indexOf(ch, pos);
-                    if (pos < 0) {
-                        throw new IllegalArgumentException("Unterminated quote in" + sql);
-                    }
-                    if (peek(sql, pos + 1) != ch) {
-                        break;
-                    }
-                    // Quoted quote char -- e.g. "abc""def" is a single string.
-                    pos += 2;
-                }
-                final int quoteEnd = pos;
-                pos++;
-
-                if (ch != '\'') {
-                    // Extract the token
-                    final String tokenUnquoted = sql.substring(quoteStart + 1, quoteEnd);
-
-                    final String token;
-
-                    // Unquote if needed. i.e. "aa""bb" -> aa"bb
-                    if (tokenUnquoted.indexOf(ch) >= 0) {
-                        token = tokenUnquoted.replaceAll(
-                                String.valueOf(ch) + ch, String.valueOf(ch));
-                    } else {
-                        token = tokenUnquoted;
-                    }
-                    checker.accept(token);
-                }
-                continue;
-            }
-            // Handle tokens enclosed in [...]
-            if (ch == '[') {
-                final int quoteStart = pos;
-                pos++;
-
-                pos = sql.indexOf(']', pos);
-                if (pos < 0) {
-                    throw new IllegalArgumentException("Unterminated quote in" + sql);
-                }
-                final int quoteEnd = pos;
-                pos++;
-
-                final String token = sql.substring(quoteStart + 1, quoteEnd);
-
-                checker.accept(token);
-                continue;
-            }
-
-            // Detect comments.
-            if (ch == '-' && peek(sql, pos + 1) == '-') {
-                pos += 2;
-                pos = sql.indexOf('\n', pos);
-                if (pos < 0) {
-                    // We disallow strings ending in an inline comment.
-                    throw new IllegalArgumentException("Unterminated comment in" + sql);
-                }
-                pos++;
-
-                continue;
-            }
-            if (ch == '/' && peek(sql, pos + 1) == '*') {
-                pos += 2;
-                pos = sql.indexOf("*/", pos);
-                if (pos < 0) {
-                    throw new IllegalArgumentException("Unterminated comment in" + sql);
-                }
-                pos += 2;
-
-                continue;
-            }
-
-            // Semicolon is never allowed.
-            if (ch == ';') {
-                throw new IllegalArgumentException("Semicolon is not allowed in " + sql);
-            }
-
-            // For this purpose, we can simply ignore other characters.
-            // (Note it doesn't handle the X'' literal properly and reports this X as a token,
-            // but that should be fine...)
-            pos++;
-        }
-    }
-}
diff --git a/src/com/android/providers/telephony/TelephonyBackupAgent.java b/src/com/android/providers/telephony/TelephonyBackupAgent.java
index 437b5a2..5c764c8 100644
--- a/src/com/android/providers/telephony/TelephonyBackupAgent.java
+++ b/src/com/android/providers/telephony/TelephonyBackupAgent.java
@@ -16,6 +16,7 @@
 
 package com.android.providers.telephony;
 
+import android.annotation.NonNull;
 import android.annotation.TargetApi;
 import android.app.AlarmManager;
 import android.app.IntentService;
@@ -319,7 +320,7 @@
         final SubscriptionManager subscriptionManager = SubscriptionManager.from(this);
         if (subscriptionManager != null) {
             final List<SubscriptionInfo> subInfo =
-                    subscriptionManager.getActiveSubscriptionInfoList(/* userVisibleonly */false);
+                    subscriptionManager.getCompleteActiveSubscriptionInfoList();
             if (subInfo != null) {
                 for (SubscriptionInfo sub : subInfo) {
                     final String phoneNumber = getNormalizedNumber(sub);
@@ -443,48 +444,54 @@
             return;
         }
 
-        int messagesWritten = 0;
+        // Backups consist of multiple chunks; each chunk consists of a set of messages
+        // of the same type in a chronological order.
+        BackupChunkInformation chunk;
         try (JsonWriter jsonWriter = getJsonWriter(fileName)) {
             if (fileName.endsWith(SMS_BACKUP_FILE_SUFFIX)) {
-                messagesWritten = putSmsMessagesToJson(cursor, jsonWriter);
+                chunk = putSmsMessagesToJson(cursor, jsonWriter);
             } else {
-                messagesWritten = putMmsMessagesToJson(cursor, jsonWriter);
+                chunk = putMmsMessagesToJson(cursor, jsonWriter);
             }
         }
-        backupFile(messagesWritten, fileName, data);
+        backupFile(chunk, fileName, data);
     }
 
     @VisibleForTesting
-    int putMmsMessagesToJson(Cursor cursor,
+    @NonNull
+    BackupChunkInformation putMmsMessagesToJson(Cursor cursor,
                              JsonWriter jsonWriter) throws IOException {
+        BackupChunkInformation results = new BackupChunkInformation();
         jsonWriter.beginArray();
-        int msgCount;
-        for (msgCount = 0; msgCount < mMaxMsgPerFile && !cursor.isAfterLast();
+        for (; results.count < mMaxMsgPerFile && !cursor.isAfterLast();
                 cursor.moveToNext()) {
-            msgCount += writeMmsToWriter(jsonWriter, cursor);
+            writeMmsToWriter(jsonWriter, cursor, results);
         }
         jsonWriter.endArray();
-        return msgCount;
+        return results;
     }
 
     @VisibleForTesting
-    int putSmsMessagesToJson(Cursor cursor, JsonWriter jsonWriter) throws IOException {
-
+    @NonNull
+    BackupChunkInformation putSmsMessagesToJson(Cursor cursor, JsonWriter jsonWriter)
+      throws IOException {
+        BackupChunkInformation results = new BackupChunkInformation();
         jsonWriter.beginArray();
-        int msgCount;
-        for (msgCount = 0; msgCount < mMaxMsgPerFile && !cursor.isAfterLast();
-                ++msgCount, cursor.moveToNext()) {
-            writeSmsToWriter(jsonWriter, cursor);
+        for (; results.count < mMaxMsgPerFile && !cursor.isAfterLast();
+                ++results.count, cursor.moveToNext()) {
+            writeSmsToWriter(jsonWriter, cursor, results);
         }
         jsonWriter.endArray();
-        return msgCount;
+        return results;
     }
 
-    private void backupFile(int messagesWritten, String fileName, FullBackupDataOutput data)
+    private void backupFile(BackupChunkInformation chunkInformation, String fileName,
+        FullBackupDataOutput data)
             throws IOException {
         final File file = new File(getFilesDir().getPath() + "/" + fileName);
+        file.setLastModified(chunkInformation.timestamp);
         try {
-            if (messagesWritten > 0) {
+            if (chunkInformation.count > 0) {
                 if (mBytesOverQuota > 0) {
                     mBytesOverQuota -= file.length();
                     return;
@@ -531,9 +538,7 @@
 
                 for (File file : files) {
                     final String fileName = file.getName();
-                    if (DEBUG) {
-                        Log.d(TAG, "onHandleIntent restoring file " + fileName);
-                    }
+                    Log.d(TAG, "onHandleIntent restoring file " + fileName);
                     try (FileInputStream fileInputStream = new FileInputStream(file)) {
                         mTelephonyBackupAgent.doRestoreFile(fileName, fileInputStream.getFD());
                         didRestore = true;
@@ -547,9 +552,7 @@
                 if (didRestore) {
                   // Tell the default sms app to do a full sync now that the messages have been
                   // restored.
-                  if (DEBUG) {
-                    Log.d(TAG, "onHandleIntent done - notifying default sms app");
-                  }
+                  Log.d(TAG, "onHandleIntent done - notifying default sms app");
                   ProviderUtil.notifyIfNotDefaultSmsApp(null /*uri*/, null /*calling package*/,
                       this);
                 }
@@ -605,25 +608,17 @@
     }
 
     private void doRestoreFile(String fileName, FileDescriptor fd) throws IOException {
-        if (DEBUG) {
-            Log.d(TAG, "Restoring file " + fileName);
-        }
+        Log.d(TAG, "Restoring file " + fileName);
 
         try (JsonReader jsonReader = getJsonReader(fd)) {
             if (fileName.endsWith(SMS_BACKUP_FILE_SUFFIX)) {
-                if (DEBUG) {
-                    Log.d(TAG, "Restoring SMS");
-                }
+                Log.d(TAG, "Restoring SMS");
                 putSmsMessagesToProvider(jsonReader);
             } else if (fileName.endsWith(MMS_BACKUP_FILE_SUFFIX)) {
-                if (DEBUG) {
-                    Log.d(TAG, "Restoring text MMS");
-                }
+                Log.d(TAG, "Restoring text MMS");
                 putMmsMessagesToProvider(jsonReader);
             } else {
-                if (DEBUG) {
-                    Log.e(TAG, "Unknown file to restore:" + fileName);
-                }
+                Log.e(TAG, "Unknown file to restore:" + fileName);
             }
         }
     }
@@ -654,6 +649,7 @@
     @VisibleForTesting
     void putMmsMessagesToProvider(JsonReader jsonReader) throws IOException {
         jsonReader.beginArray();
+        int total = 0;
         while (jsonReader.hasNext()) {
             final Mms mms = readMmsFromReader(jsonReader);
             if (DEBUG) {
@@ -662,11 +658,15 @@
             if (doesMmsExist(mms)) {
                 if (DEBUG) {
                     Log.e(TAG, String.format("Mms: %s already exists", mms.toString()));
+                } else {
+                    Log.w(TAG, "Mms: Found duplicate MMS");
                 }
                 continue;
             }
+            total++;
             addMmsMessage(mms);
         }
+        Log.d(TAG, "putMmsMessagesToProvider handled " + total + " new messages.");
     }
 
     @VisibleForTesting
@@ -706,11 +706,19 @@
         if (subscriptionInfo == null) {
             return null;
         }
-        return PhoneNumberUtils.formatNumberToE164(subscriptionInfo.getNumber(),
-                subscriptionInfo.getCountryIso().toUpperCase(Locale.US));
+        // country iso might not be always available in some corner cases (e.g. mis-configured SIM,
+        // carrier config, or test SIM has incorrect IMSI, etc...). In that case, just return the
+        // unformatted number.
+        if (!TextUtils.isEmpty(subscriptionInfo.getCountryIso())) {
+            return PhoneNumberUtils.formatNumberToE164(subscriptionInfo.getNumber(),
+                    subscriptionInfo.getCountryIso().toUpperCase(Locale.US));
+        } else {
+            return subscriptionInfo.getNumber();
+        }
     }
 
-    private void writeSmsToWriter(JsonWriter jsonWriter, Cursor cursor) throws IOException {
+    private void writeSmsToWriter(JsonWriter jsonWriter, Cursor cursor,
+            BackupChunkInformation chunk) throws IOException {
         jsonWriter.beginObject();
 
         for (int i=0; i<cursor.getColumnCount(); ++i) {
@@ -733,12 +741,31 @@
                     break;
                 case Telephony.Sms._ID:
                     break;
+                case Telephony.Sms.DATE:
+                case Telephony.Sms.DATE_SENT:
+                    chunk.timestamp = findNewestValue(chunk.timestamp, value);
+                    jsonWriter.name(name).value(value);
+                    break;
                 default:
                     jsonWriter.name(name).value(value);
                     break;
             }
         }
         jsonWriter.endObject();
+    }
+
+    private long findNewestValue(long current, String latest) {
+        if(latest == null) {
+            return current;
+        }
+
+        try {
+            long latestLong = Long.valueOf(latest);
+            return Math.max(current, latestLong);
+        } catch (NumberFormatException e) {
+            Log.d(TAG, "Unable to parse value "+latest);
+            return current;
+        }
 
     }
 
@@ -823,6 +850,8 @@
                 default:
                     if (DEBUG) {
                         Log.w(TAG, "readSmsValuesFromReader Unknown name:" + name);
+                    } else {
+                        Log.w(TAG, "readSmsValuesFromReader encountered unknown name.");
                     }
                     jsonReader.skipValue();
                     break;
@@ -843,12 +872,13 @@
         return recipients;
     }
 
-    private int writeMmsToWriter(JsonWriter jsonWriter, Cursor cursor) throws IOException {
+    private void writeMmsToWriter(JsonWriter jsonWriter, Cursor cursor,
+            BackupChunkInformation chunk) throws IOException {
         final int mmsId = cursor.getInt(ID_IDX);
         final MmsBody body = getMmsBody(mmsId);
         // We backup any message that contains text, but only backup the text part.
         if (body == null || body.text == null) {
-            return 0;
+            return;
         }
 
         boolean subjectNull = true;
@@ -877,6 +907,11 @@
                 case Telephony.Mms._ID:
                 case Telephony.Mms.SUBJECT_CHARSET:
                     break;
+                case Telephony.Mms.DATE:
+                case Telephony.Mms.DATE_SENT:
+                    chunk.timestamp = findNewestValue(chunk.timestamp, value);
+                    jsonWriter.name(name).value(value);
+                    break;
                 case Telephony.Mms.SUBJECT:
                     subjectNull = false;
                 default:
@@ -896,7 +931,7 @@
             writeStringToWriter(jsonWriter, cursor, Telephony.Mms.SUBJECT_CHARSET);
         }
         jsonWriter.endObject();
-        return 1;
+        chunk.count++;
     }
 
     private Mms readMmsFromReader(JsonReader jsonReader) throws IOException {
@@ -955,9 +990,7 @@
                     mms.values.put(name, jsonReader.nextString());
                     break;
                 default:
-                    if (DEBUG) {
-                        Log.d(TAG, "Unknown name:" + name);
-                    }
+                    Log.d(TAG, "Unknown JSON element name:" + name);
                     jsonReader.skipValue();
                     break;
             }
@@ -995,9 +1028,7 @@
                 values,
                 ARCHIVE_THREAD_SELECTION,
                 new String[] { Long.toString(threadId)}) != 1) {
-            if (DEBUG) {
-                Log.e(TAG, "archiveThread: failed to update database");
-            }
+            Log.e(TAG, "archiveThread: failed to update database");
         }
     }
 
@@ -1066,9 +1097,7 @@
                         addrValues.put(name, jsonReader.nextString());
                         break;
                     default:
-                        if (DEBUG) {
-                            Log.d(TAG, "Unknown name:" + name);
-                        }
+                        Log.d(TAG, "Unknown JSON Element name:" + name);
                         jsonReader.skipValue();
                         break;
                 }
@@ -1099,9 +1128,7 @@
                         attachmentValues.put(name, jsonReader.nextString());
                         break;
                     default:
-                        if (DEBUG) {
-                            Log.d(TAG, "getMmsAttachmentsFromReader Unknown name:" + name);
-                        }
+                        Log.d(TAG, "getMmsAttachmentsFromReader Unknown name:" + name);
                         jsonReader.skipValue();
                         break;
                 }
@@ -1110,9 +1137,7 @@
             if (attachmentValues.containsKey(MMS_ATTACHMENT_FILENAME)) {
                 mms.attachments.add(attachmentValues);
             } else {
-                if (DEBUG) {
-                    Log.d(TAG, "Attachment json with no filenames");
-                }
+                Log.d(TAG, "Attachment json with no filenames");
             }
         }
         jsonReader.endArray();
@@ -1140,9 +1165,7 @@
             values.put(Telephony.Mms.Part.CONTENT_LOCATION, "smil.xml");
             values.put(Telephony.Mms.Part.TEXT, smil);
             if (mContentResolver.insert(partUri, values) == null) {
-                if (DEBUG) {
-                    Log.e(TAG, "Could not insert SMIL part");
-                }
+                Log.e(TAG, "Could not insert SMIL part");
                 return;
             }
         }
@@ -1162,9 +1185,7 @@
             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");
-                }
+                Log.e(TAG, "Could not insert body part");
                 return;
             }
         }
@@ -1184,9 +1205,7 @@
                         getDataDir() + ATTACHMENT_DATA_PATH + filename);
                 Uri newPartUri = mContentResolver.insert(partUri, values);
                 if (newPartUri == null) {
-                    if (DEBUG) {
-                        Log.e(TAG, "Could not insert attachment part");
-                    }
+                    Log.e(TAG, "Could not insert attachment part");
                     return;
                 }
             }
@@ -1195,9 +1214,7 @@
         // Insert mms.
         final Uri mmsUri = mContentResolver.insert(Telephony.Mms.CONTENT_URI, mms.values);
         if (mmsUri == null) {
-            if (DEBUG) {
-                Log.e(TAG, "Could not insert mms");
-            }
+            Log.e(TAG, "Could not insert mms");
             return;
         }
 
@@ -1301,9 +1318,7 @@
             try {
                 threadId = Telephony.Threads.getOrCreateThreadId(this, recipients);
             } catch (RuntimeException e) {
-                if (DEBUG) {
-                    Log.e(TAG, e.toString());
-                }
+                Log.e(TAG, "Problem obtaining thread.", e);
             }
             mCacheGetOrCreateThreadId.put(recipients, threadId);
             return threadId;
@@ -1377,15 +1392,11 @@
             try {
                 longId = Long.parseLong(id);
                 if (longId < 0) {
-                    if (DEBUG) {
-                        Log.e(TAG, "getAddresses: invalid id " + longId);
-                    }
+                    Log.e(TAG, "getAddresses: invalid id " + longId);
                     continue;
                 }
             } catch (final NumberFormatException ex) {
-                if (DEBUG) {
-                    Log.e(TAG, "getAddresses: invalid id. " + ex, ex);
-                }
+                Log.e(TAG, "getAddresses: invalid id " + ex, ex);
                 // skip this id
                 continue;
             }
@@ -1397,10 +1408,9 @@
                         ContentUris.withAppendedId(SINGLE_CANONICAL_ADDRESS_URI, longId),
                         null, null, null, null);
             } catch (final Exception e) {
-                if (DEBUG) {
-                    Log.e(TAG, "getAddresses: query failed for id " + longId, e);
-                }
+                Log.e(TAG, "getAddresses: query failed for id " + longId, e);
             }
+
             if (c != null) {
                 try {
                     if (c.moveToFirst()) {
@@ -1408,9 +1418,7 @@
                         if (!TextUtils.isEmpty(number)) {
                             numbers.add(number);
                         } else {
-                            if (DEBUG) {
-                                Log.d(TAG, "Canonical MMS/SMS address is empty for id: " + longId);
-                            }
+                            Log.d(TAG, "Canonical MMS/SMS address is empty for id: " + longId);
                         }
                     }
                 } finally {
@@ -1419,9 +1427,7 @@
             }
         }
         if (numbers.isEmpty()) {
-            if (DEBUG) {
-                Log.d(TAG, "No MMS addresses found from ids string [" + spaceSepIds + "]");
-            }
+            Log.d(TAG, "No MMS addresses found from ids string [" + spaceSepIds + "]");
         }
         return numbers;
     }
@@ -1441,4 +1447,12 @@
     public static boolean getIsRestoring() {
         return sIsRestoring;
     }
+
+    private static class BackupChunkInformation {
+        // Timestamp of the recent message in the file
+        private long timestamp;
+
+        // The number of messages in the backup file
+        private int count = 0;
+    }
 }
diff --git a/src/com/android/providers/telephony/TelephonyProvider.java b/src/com/android/providers/telephony/TelephonyProvider.java
index c564a07..4966e5a 100644
--- a/src/com/android/providers/telephony/TelephonyProvider.java
+++ b/src/com/android/providers/telephony/TelephonyProvider.java
@@ -70,6 +70,8 @@
 import static android.provider.Telephony.Carriers.WAIT_TIME_RETRY;
 import static android.provider.Telephony.Carriers._ID;
 
+import android.annotation.NonNull;
+import android.app.compat.CompatChanges;
 import android.content.ComponentName;
 import android.content.ContentProvider;
 import android.content.ContentResolver;
@@ -93,51 +95,49 @@
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Environment;
-import android.os.FileUtils;
 import android.os.IBinder;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.provider.Telephony;
-import android.telephony.ServiceState;
-import android.telephony.SubscriptionInfo;
+import android.telephony.Annotation;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.telephony.data.ApnSetting;
 import android.text.TextUtils;
-import android.util.EventLog;
+import android.util.ArrayMap;
 import android.util.Log;
 import android.util.Pair;
 import android.util.Xml;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.telephony.IApnSourceService;
-import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.PhoneFactory;
-import com.android.internal.telephony.dataconnection.ApnSettingUtils;
-import com.android.internal.telephony.uicc.IccRecords;
-import com.android.internal.telephony.uicc.UiccController;
 import com.android.internal.util.XmlUtils;
+import android.service.carrier.IApnSourceService;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
+import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
+import java.util.zip.CheckedInputStream;
 import java.util.zip.CRC32;
 
 public class TelephonyProvider extends ContentProvider
@@ -147,7 +147,7 @@
     private static final boolean DBG = true;
     private static final boolean VDBG = false; // STOPSHIP if true
 
-    private static final int DATABASE_VERSION = 42 << 16;
+    private static final int DATABASE_VERSION = 45 << 16;
     private static final int URL_UNKNOWN = 0;
     private static final int URL_TELEPHONY = 1;
     private static final int URL_CURRENT = 2;
@@ -177,6 +177,11 @@
     private static final int URL_SIM_APN_LIST_FILTERED = 26;
     private static final int URL_SIM_APN_LIST_FILTERED_ID = 27;
 
+    /**
+     * Default value for mtu if it's not set. Moved from PhoneConstants.
+     */
+    private static final int UNSPECIFIED_INT = -1;
+
     private static final String TAG = "TelephonyProvider";
     private static final String CARRIERS_TABLE = "carriers";
     private static final String CARRIERS_TABLE_TMP = "carriers_tmp";
@@ -207,10 +212,6 @@
     private static final String DEFAULT_PROTOCOL = "IP";
     private static final String DEFAULT_ROAMING_PROTOCOL = "IP";
 
-    // Used to check if certain queries contain subqueries that may attempt to access sensitive
-    // fields in the carriers db.
-    private static final String SQL_SELECT_TOKEN = "select";
-
     private static final UriMatcher s_urlMatcher = new UriMatcher(UriMatcher.NO_MATCH);
 
     private static final ContentValues s_currentNullMap;
@@ -238,7 +239,7 @@
     private static final String IS_NOT_OWNED_BY_DPC = OWNED_BY + "!=" + OWNED_BY_DPC;
 
     private static final String ORDER_BY_SUB_ID =
-            SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + " ASC";
+            Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID + " ASC";
 
     private static final int INVALID_APN_ID = -1;
     private static final List<String> CARRIERS_UNIQUE_FIELDS = new ArrayList<String>();
@@ -255,6 +256,57 @@
 
     private boolean mManagedApnEnforced;
 
+    /**
+     * Available radio technologies for GSM, UMTS and CDMA.
+     * Duplicates the constants from hardware/radio/include/ril.h
+     * This should only be used by agents working with the ril.  Others
+     * should use the equivalent TelephonyManager.NETWORK_TYPE_*
+     */
+    private static final int RIL_RADIO_TECHNOLOGY_UNKNOWN = 0;
+    private static final int RIL_RADIO_TECHNOLOGY_GPRS = 1;
+    private static final int RIL_RADIO_TECHNOLOGY_EDGE = 2;
+    private static final int RIL_RADIO_TECHNOLOGY_UMTS = 3;
+    private static final int RIL_RADIO_TECHNOLOGY_IS95A = 4;
+    private static final int RIL_RADIO_TECHNOLOGY_IS95B = 5;
+    private static final int RIL_RADIO_TECHNOLOGY_1xRTT = 6;
+    private static final int RIL_RADIO_TECHNOLOGY_EVDO_0 = 7;
+    private static final int RIL_RADIO_TECHNOLOGY_EVDO_A = 8;
+    private static final int RIL_RADIO_TECHNOLOGY_HSDPA = 9;
+    private static final int RIL_RADIO_TECHNOLOGY_HSUPA = 10;
+    private static final int RIL_RADIO_TECHNOLOGY_HSPA = 11;
+    private static final int RIL_RADIO_TECHNOLOGY_EVDO_B = 12;
+    private static final int RIL_RADIO_TECHNOLOGY_EHRPD = 13;
+    private static final int RIL_RADIO_TECHNOLOGY_LTE = 14;
+    private static final int RIL_RADIO_TECHNOLOGY_HSPAP = 15;
+
+    /**
+     * GSM radio technology only supports voice. It does not support data.
+     */
+    private static final int RIL_RADIO_TECHNOLOGY_GSM = 16;
+    private static final int RIL_RADIO_TECHNOLOGY_TD_SCDMA = 17;
+
+    /**
+     * IWLAN
+     */
+    private static final int RIL_RADIO_TECHNOLOGY_IWLAN = 18;
+
+    /**
+     * LTE_CA
+     */
+    private static final int RIL_RADIO_TECHNOLOGY_LTE_CA = 19;
+
+    /**
+     * NR(New Radio) 5G.
+     */
+    private static final int  RIL_RADIO_TECHNOLOGY_NR = 20;
+
+    /**
+     * The number of the radio technologies.
+     */
+    private static final int NEXT_RIL_RADIO_TECHNOLOGY = 21;
+
+    private static final Map<String, Integer> MVNO_TYPE_STRING_MAP;
+
     static {
         // Columns not included in UNIQUE constraint: name, current, edited, user, server, password,
         // authtype, type, protocol, roaming_protocol, sub_id, modem_cognitive, max_conns,
@@ -291,6 +343,12 @@
         CARRIERS_BOOLEAN_FIELDS.add(MODEM_PERSIST);
         CARRIERS_BOOLEAN_FIELDS.add(USER_VISIBLE);
         CARRIERS_BOOLEAN_FIELDS.add(USER_EDITABLE);
+
+        MVNO_TYPE_STRING_MAP = new ArrayMap<String, Integer>();
+        MVNO_TYPE_STRING_MAP.put("spn", ApnSetting.MVNO_TYPE_SPN);
+        MVNO_TYPE_STRING_MAP.put("imsi", ApnSetting.MVNO_TYPE_IMSI);
+        MVNO_TYPE_STRING_MAP.put("gid", ApnSetting.MVNO_TYPE_GID);
+        MVNO_TYPE_STRING_MAP.put("iccid", ApnSetting.MVNO_TYPE_ICCID);
     }
 
     @VisibleForTesting
@@ -348,66 +406,68 @@
     @VisibleForTesting
     public static String getStringForSimInfoTableCreation(String tableName) {
         return "CREATE TABLE " + tableName + "("
-                + SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID
+                + Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID
                 + " INTEGER PRIMARY KEY AUTOINCREMENT,"
-                + SubscriptionManager.ICC_ID + " TEXT NOT NULL,"
-                + SubscriptionManager.SIM_SLOT_INDEX
-                + " INTEGER DEFAULT " + SubscriptionManager.SIM_NOT_INSERTED + ","
-                + SubscriptionManager.DISPLAY_NAME + " TEXT,"
-                + SubscriptionManager.CARRIER_NAME + " TEXT,"
-                + SubscriptionManager.NAME_SOURCE
-                + " INTEGER DEFAULT " + SubscriptionManager.NAME_SOURCE_DEFAULT_SOURCE + ","
-                + SubscriptionManager.COLOR + " INTEGER DEFAULT "
-                + SubscriptionManager.COLOR_DEFAULT + ","
-                + SubscriptionManager.NUMBER + " TEXT,"
-                + SubscriptionManager.DISPLAY_NUMBER_FORMAT
-                + " INTEGER NOT NULL DEFAULT " + SubscriptionManager.DISPLAY_NUMBER_DEFAULT + ","
-                + SubscriptionManager.DATA_ROAMING
-                + " INTEGER DEFAULT " + SubscriptionManager.DATA_ROAMING_DEFAULT + ","
-                + SubscriptionManager.MCC + " INTEGER DEFAULT 0,"
-                + SubscriptionManager.MNC + " INTEGER DEFAULT 0,"
-                + SubscriptionManager.MCC_STRING + " TEXT,"
-                + SubscriptionManager.MNC_STRING + " TEXT,"
-                + SubscriptionManager.EHPLMNS + " TEXT,"
-                + SubscriptionManager.HPLMNS + " TEXT,"
-                + SubscriptionManager.SIM_PROVISIONING_STATUS
-                + " INTEGER DEFAULT " + SubscriptionManager.SIM_PROVISIONED + ","
-                + SubscriptionManager.IS_EMBEDDED + " INTEGER DEFAULT 0,"
-                + SubscriptionManager.CARD_ID + " TEXT NOT NULL,"
-                + SubscriptionManager.ACCESS_RULES + " BLOB,"
-                + SubscriptionManager.ACCESS_RULES_FROM_CARRIER_CONFIGS + " BLOB,"
-                + SubscriptionManager.IS_REMOVABLE + " INTEGER DEFAULT 0,"
-                + SubscriptionManager.CB_EXTREME_THREAT_ALERT + " INTEGER DEFAULT 1,"
-                + SubscriptionManager.CB_SEVERE_THREAT_ALERT + " INTEGER DEFAULT 1,"
-                + SubscriptionManager.CB_AMBER_ALERT + " INTEGER DEFAULT 1,"
-                + SubscriptionManager.CB_EMERGENCY_ALERT + " INTEGER DEFAULT 1,"
-                + SubscriptionManager.CB_ALERT_SOUND_DURATION + " INTEGER DEFAULT 4,"
-                + SubscriptionManager.CB_ALERT_REMINDER_INTERVAL + " INTEGER DEFAULT 0,"
-                + SubscriptionManager.CB_ALERT_VIBRATE + " INTEGER DEFAULT 1,"
-                + SubscriptionManager.CB_ALERT_SPEECH + " INTEGER DEFAULT 1,"
-                + SubscriptionManager.CB_ETWS_TEST_ALERT + " INTEGER DEFAULT 0,"
-                + SubscriptionManager.CB_CHANNEL_50_ALERT + " INTEGER DEFAULT 1,"
-                + SubscriptionManager.CB_CMAS_TEST_ALERT + " INTEGER DEFAULT 0,"
-                + SubscriptionManager.CB_OPT_OUT_DIALOG + " INTEGER DEFAULT 1,"
-                + SubscriptionManager.ENHANCED_4G_MODE_ENABLED + " INTEGER DEFAULT -1,"
-                + SubscriptionManager.VT_IMS_ENABLED + " INTEGER DEFAULT -1,"
-                + SubscriptionManager.WFC_IMS_ENABLED + " INTEGER DEFAULT -1,"
-                + SubscriptionManager.WFC_IMS_MODE + " INTEGER DEFAULT -1,"
-                + SubscriptionManager.WFC_IMS_ROAMING_MODE + " INTEGER DEFAULT -1,"
-                + SubscriptionManager.WFC_IMS_ROAMING_ENABLED + " INTEGER DEFAULT -1,"
-                + SubscriptionManager.IS_OPPORTUNISTIC + " INTEGER DEFAULT 0,"
-                + SubscriptionManager.GROUP_UUID + " TEXT,"
-                + SubscriptionManager.IS_METERED + " INTEGER DEFAULT 1,"
-                + SubscriptionManager.ISO_COUNTRY_CODE + " TEXT,"
-                + SubscriptionManager.CARRIER_ID + " INTEGER DEFAULT -1,"
-                + SubscriptionManager.PROFILE_CLASS + " INTEGER DEFAULT "
-                + SubscriptionManager.PROFILE_CLASS_DEFAULT + ","
-                + SubscriptionManager.SUBSCRIPTION_TYPE + " INTEGER DEFAULT "
-                + SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM + ","
-                + SubscriptionManager.WHITE_LISTED_APN_DATA + " INTEGER DEFAULT 0,"
-                + SubscriptionManager.GROUP_OWNER + " TEXT,"
-                + SubscriptionManager.DATA_ENABLED_OVERRIDE_RULES + " TEXT,"
-                + SubscriptionManager.IMSI + " TEXT"
+                + Telephony.SimInfo.COLUMN_ICC_ID + " TEXT NOT NULL,"
+                + Telephony.SimInfo.COLUMN_SIM_SLOT_INDEX
+                + " INTEGER DEFAULT " + Telephony.SimInfo.SIM_NOT_INSERTED + ","
+                + Telephony.SimInfo.COLUMN_DISPLAY_NAME + " TEXT,"
+                + Telephony.SimInfo.COLUMN_CARRIER_NAME + " TEXT,"
+                + Telephony.SimInfo.COLUMN_NAME_SOURCE
+                + " INTEGER DEFAULT " + Telephony.SimInfo.NAME_SOURCE_CARRIER_ID + ","
+                + Telephony.SimInfo.COLUMN_COLOR + " INTEGER DEFAULT "
+                + Telephony.SimInfo.COLOR_DEFAULT + ","
+                + Telephony.SimInfo.COLUMN_NUMBER + " TEXT,"
+                + Telephony.SimInfo.COLUMN_DISPLAY_NUMBER_FORMAT
+                + " INTEGER NOT NULL DEFAULT " + Telephony.SimInfo.DISPLAY_NUMBER_DEFAULT + ","
+                + Telephony.SimInfo.COLUMN_DATA_ROAMING
+                + " INTEGER DEFAULT " + Telephony.SimInfo.DATA_ROAMING_DISABLE + ","
+                + Telephony.SimInfo.COLUMN_MCC + " INTEGER DEFAULT 0,"
+                + Telephony.SimInfo.COLUMN_MNC + " INTEGER DEFAULT 0,"
+                + Telephony.SimInfo.COLUMN_MCC_STRING + " TEXT,"
+                + Telephony.SimInfo.COLUMN_MNC_STRING + " TEXT,"
+                + Telephony.SimInfo.COLUMN_EHPLMNS + " TEXT,"
+                + Telephony.SimInfo.COLUMN_HPLMNS + " TEXT,"
+                + Telephony.SimInfo.COLUMN_SIM_PROVISIONING_STATUS
+                + " INTEGER DEFAULT " + Telephony.SimInfo.SIM_PROVISIONED + ","
+                + Telephony.SimInfo.COLUMN_IS_EMBEDDED + " INTEGER DEFAULT 0,"
+                + Telephony.SimInfo.COLUMN_CARD_ID + " TEXT NOT NULL,"
+                + Telephony.SimInfo.COLUMN_ACCESS_RULES + " BLOB,"
+                + Telephony.SimInfo.COLUMN_ACCESS_RULES_FROM_CARRIER_CONFIGS + " BLOB,"
+                + Telephony.SimInfo.COLUMN_IS_REMOVABLE + " INTEGER DEFAULT 0,"
+                + Telephony.SimInfo.COLUMN_CB_EXTREME_THREAT_ALERT + " INTEGER DEFAULT 1,"
+                + Telephony.SimInfo.COLUMN_CB_SEVERE_THREAT_ALERT + " INTEGER DEFAULT 1,"
+                + Telephony.SimInfo.COLUMN_CB_AMBER_ALERT + " INTEGER DEFAULT 1,"
+                + Telephony.SimInfo.COLUMN_CB_EMERGENCY_ALERT + " INTEGER DEFAULT 1,"
+                + Telephony.SimInfo.COLUMN_CB_ALERT_SOUND_DURATION + " INTEGER DEFAULT 4,"
+                + Telephony.SimInfo.COLUMN_CB_ALERT_REMINDER_INTERVAL + " INTEGER DEFAULT 0,"
+                + Telephony.SimInfo.COLUMN_CB_ALERT_VIBRATE + " INTEGER DEFAULT 1,"
+                + Telephony.SimInfo.COLUMN_CB_ALERT_SPEECH + " INTEGER DEFAULT 1,"
+                + Telephony.SimInfo.COLUMN_CB_ETWS_TEST_ALERT + " INTEGER DEFAULT 0,"
+                + Telephony.SimInfo.COLUMN_CB_CHANNEL_50_ALERT + " INTEGER DEFAULT 1,"
+                + Telephony.SimInfo.COLUMN_CB_CMAS_TEST_ALERT + " INTEGER DEFAULT 0,"
+                + Telephony.SimInfo.COLUMN_CB_OPT_OUT_DIALOG + " INTEGER DEFAULT 1,"
+                + Telephony.SimInfo.COLUMN_ENHANCED_4G_MODE_ENABLED + " INTEGER DEFAULT -1,"
+                + Telephony.SimInfo.COLUMN_VT_IMS_ENABLED + " INTEGER DEFAULT -1,"
+                + Telephony.SimInfo.COLUMN_WFC_IMS_ENABLED + " INTEGER DEFAULT -1,"
+                + Telephony.SimInfo.COLUMN_WFC_IMS_MODE + " INTEGER DEFAULT -1,"
+                + Telephony.SimInfo.COLUMN_WFC_IMS_ROAMING_MODE + " INTEGER DEFAULT -1,"
+                + Telephony.SimInfo.COLUMN_WFC_IMS_ROAMING_ENABLED + " INTEGER DEFAULT -1,"
+                + Telephony.SimInfo.COLUMN_IS_OPPORTUNISTIC + " INTEGER DEFAULT 0,"
+                + Telephony.SimInfo.COLUMN_GROUP_UUID + " TEXT,"
+                + Telephony.SimInfo.COLUMN_IS_METERED + " INTEGER DEFAULT 1,"
+                + Telephony.SimInfo.COLUMN_ISO_COUNTRY_CODE + " TEXT,"
+                + Telephony.SimInfo.COLUMN_CARRIER_ID + " INTEGER DEFAULT -1,"
+                + Telephony.SimInfo.COLUMN_PROFILE_CLASS + " INTEGER DEFAULT "
+                + Telephony.SimInfo.PROFILE_CLASS_UNSET + ","
+                + Telephony.SimInfo.COLUMN_SUBSCRIPTION_TYPE + " INTEGER DEFAULT "
+                + Telephony.SimInfo.SUBSCRIPTION_TYPE_LOCAL_SIM + ","
+                + Telephony.SimInfo.COLUMN_GROUP_OWNER + " TEXT,"
+                + Telephony.SimInfo.COLUMN_DATA_ENABLED_OVERRIDE_RULES + " TEXT,"
+                + Telephony.SimInfo.COLUMN_IMSI + " TEXT,"
+                + Telephony.SimInfo.COLUMN_UICC_APPLICATIONS_ENABLED + " INTEGER DEFAULT 1,"
+                + Telephony.SimInfo.COLUMN_ALLOWED_NETWORK_TYPES + " BIGINT DEFAULT -1,"
+                + Telephony.SimInfo.COLUMN_IMS_RCS_UCE_ENABLED + " INTEGER DEFAULT 0"
                 + ");";
     }
 
@@ -484,7 +544,41 @@
     }
 
     @VisibleForTesting
-    public static class DatabaseHelper extends SQLiteOpenHelper {
+    public static int getVersion(Context context) {
+        if (VDBG) log("getVersion:+");
+        // Get the database version, combining a static schema version and the XML version
+        Resources r = context.getResources();
+        if (r == null) {
+            loge("resources=null, return version=" + Integer.toHexString(DATABASE_VERSION));
+            return DATABASE_VERSION;
+        }
+        XmlResourceParser parser = r.getXml(com.android.internal.R.xml.apns);
+        try {
+            XmlUtils.beginDocument(parser, "apns");
+            int publicversion = Integer.parseInt(parser.getAttributeValue(null, "version"));
+            int version = DATABASE_VERSION | publicversion;
+            if (VDBG) log("getVersion:- version=0x" + Integer.toHexString(version));
+            return version;
+        } catch (Exception e) {
+            loge("Can't get version of APN database" + e + " return version=" +
+                    Integer.toHexString(DATABASE_VERSION));
+            return DATABASE_VERSION;
+        } finally {
+            parser.close();
+        }
+    }
+
+    static public ContentValues setDefaultValue(ContentValues values) {
+        if (!values.containsKey(SUBSCRIPTION_ID)) {
+            int subId = SubscriptionManager.getDefaultSubscriptionId();
+            values.put(SUBSCRIPTION_ID, subId);
+        }
+
+        return values;
+    }
+
+    @VisibleForTesting
+    public class DatabaseHelper extends SQLiteOpenHelper {
         // Context to access resources with
         private Context mContext;
 
@@ -501,31 +595,6 @@
             setWriteAheadLoggingEnabled(false);
         }
 
-        @VisibleForTesting
-        public static int getVersion(Context context) {
-            if (VDBG) log("getVersion:+");
-            // Get the database version, combining a static schema version and the XML version
-            Resources r = context.getResources();
-            if (r == null) {
-                loge("resources=null, return version=" + Integer.toHexString(DATABASE_VERSION));
-                return DATABASE_VERSION;
-            }
-            XmlResourceParser parser = r.getXml(com.android.internal.R.xml.apns);
-            try {
-                XmlUtils.beginDocument(parser, "apns");
-                int publicversion = Integer.parseInt(parser.getAttributeValue(null, "version"));
-                int version = DATABASE_VERSION | publicversion;
-                if (VDBG) log("getVersion:- version=0x" + Integer.toHexString(version));
-                return version;
-            } catch (Exception e) {
-                loge("Can't get version of APN database" + e + " return version=" +
-                        Integer.toHexString(DATABASE_VERSION));
-                return DATABASE_VERSION;
-            } finally {
-                parser.close();
-            }
-        }
-
         @Override
         public void onCreate(SQLiteDatabase db) {
             if (DBG) log("dbh.onCreate:+ db=" + db);
@@ -580,10 +649,18 @@
         }
 
         private long getChecksum(File file) {
-            long checksum = -1;
-            try {
-                checksum = FileUtils.checksumCrc32(file);
-                if (DBG) log("Checksum for " + file.getAbsolutePath() + " is " + checksum);
+            CRC32 checkSummer = new CRC32();
+            long checkSum = -1;
+            try (CheckedInputStream cis =
+                new CheckedInputStream(new FileInputStream(file), checkSummer)){
+                byte[] buf = new byte[128];
+                if(cis != null) {
+                    while(cis.read(buf) >= 0) {
+                        // Just read for checksum to get calculated.
+                    }
+                }
+                checkSum = checkSummer.getValue();
+                if (DBG) log("Checksum for " + file.getAbsolutePath() + " is " + checkSum);
             } catch (FileNotFoundException e) {
                 loge("FileNotFoundException for " + file.getAbsolutePath() + ":" + e);
             } catch (IOException e) {
@@ -595,17 +672,17 @@
             try (InputStream inputStream = mContext.getResources().
                         openRawResource(com.android.internal.R.xml.apns)) {
                 byte[] array = toByteArray(inputStream);
-                CRC32 c = new CRC32();
-                c.update(array);
-                checksum += c.getValue();
-                if (DBG) log("Checksum after adding resource is " + checksum);
+                checkSummer.reset();
+                checkSummer.update(array);
+                checkSum += checkSummer.getValue();
+                if (DBG) log("Checksum after adding resource is " + checkSummer.getValue());
             } catch (IOException | Resources.NotFoundException e) {
                 loge("Exception when calculating checksum for internal apn resources: " + e);
             }
-            return checksum;
+            return checkSum;
         }
 
-        private static byte[] toByteArray(InputStream input) throws IOException {
+        private byte[] toByteArray(InputStream input) throws IOException {
             byte[] buffer = new byte[128];
             int bytesRead;
             ByteArrayOutputStream output = new ByteArrayOutputStream();
@@ -763,6 +840,8 @@
                 log("dbh.onUpgrade:+ db=" + db + " oldV=" + oldVersion + " newV=" + newVersion);
             }
 
+            deletePreferredApnId(mContext);
+
             if (oldVersion < (5 << 16 | 6)) {
                 // 5 << 16 is the Database version and 6 in the xml version.
 
@@ -834,9 +913,9 @@
                 try {
                     // Try to update the siminfo table. It might not be there.
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE +
-                            " ADD COLUMN " + SubscriptionManager.MCC + " INTEGER DEFAULT 0;");
+                            " ADD COLUMN " + Telephony.SimInfo.COLUMN_MCC + " INTEGER DEFAULT 0;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE +
-                            " ADD COLUMN " + SubscriptionManager.MNC + " INTEGER DEFAULT 0;");
+                            " ADD COLUMN " + Telephony.SimInfo.COLUMN_MNC + " INTEGER DEFAULT 0;");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -849,7 +928,7 @@
                 try {
                     // Try to update the siminfo table. It might not be there.
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " +
-                            SubscriptionManager.CARRIER_NAME + " TEXT DEFAULT '';");
+                            Telephony.SimInfo.COLUMN_CARRIER_NAME + " TEXT DEFAULT '';");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -932,29 +1011,33 @@
                     // These columns may already be present in which case execSQL will throw an
                     // exception
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.CB_EXTREME_THREAT_ALERT + " INTEGER DEFAULT 1;");
+                            + Telephony.SimInfo.COLUMN_CB_EXTREME_THREAT_ALERT
+                            + " INTEGER DEFAULT 1;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.CB_SEVERE_THREAT_ALERT + " INTEGER DEFAULT 1;");
+                            + Telephony.SimInfo.COLUMN_CB_SEVERE_THREAT_ALERT
+                            + " INTEGER DEFAULT 1;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.CB_AMBER_ALERT + " INTEGER DEFAULT 1;");
+                            + Telephony.SimInfo.COLUMN_CB_AMBER_ALERT + " INTEGER DEFAULT 1;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.CB_EMERGENCY_ALERT + " INTEGER DEFAULT 1;");
+                            + Telephony.SimInfo.COLUMN_CB_EMERGENCY_ALERT + " INTEGER DEFAULT 1;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.CB_ALERT_SOUND_DURATION + " INTEGER DEFAULT 4;");
+                            + Telephony.SimInfo.COLUMN_CB_ALERT_SOUND_DURATION
+                            + " INTEGER DEFAULT 4;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.CB_ALERT_REMINDER_INTERVAL + " INTEGER DEFAULT 0;");
+                            + Telephony.SimInfo.COLUMN_CB_ALERT_REMINDER_INTERVAL
+                            + " INTEGER DEFAULT 0;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.CB_ALERT_VIBRATE + " INTEGER DEFAULT 1;");
+                            + Telephony.SimInfo.COLUMN_CB_ALERT_VIBRATE + " INTEGER DEFAULT 1;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.CB_ALERT_SPEECH + " INTEGER DEFAULT 1;");
+                            + Telephony.SimInfo.COLUMN_CB_ALERT_SPEECH + " INTEGER DEFAULT 1;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.CB_ETWS_TEST_ALERT + " INTEGER DEFAULT 0;");
+                            + Telephony.SimInfo.COLUMN_CB_ETWS_TEST_ALERT + " INTEGER DEFAULT 0;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.CB_CHANNEL_50_ALERT + " INTEGER DEFAULT 1;");
+                            + Telephony.SimInfo.COLUMN_CB_CHANNEL_50_ALERT + " INTEGER DEFAULT 1;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.CB_CMAS_TEST_ALERT + " INTEGER DEFAULT 0;");
+                            + Telephony.SimInfo.COLUMN_CB_CMAS_TEST_ALERT + " INTEGER DEFAULT 0;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.CB_OPT_OUT_DIALOG + " INTEGER DEFAULT 1;");
+                            + Telephony.SimInfo.COLUMN_CB_OPT_OUT_DIALOG + " INTEGER DEFAULT 1;");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -988,8 +1071,8 @@
                 try {
                     // Try to update the siminfo table. It might not be there.
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " +
-                            SubscriptionManager.SIM_PROVISIONING_STATUS + " INTEGER DEFAULT " +
-                            SubscriptionManager.SIM_PROVISIONED + ";");
+                            Telephony.SimInfo.COLUMN_SIM_PROVISIONING_STATUS + " INTEGER DEFAULT " +
+                            Telephony.SimInfo.SIM_PROVISIONED + ";");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -1007,11 +1090,11 @@
                 try {
                     // Try to update the siminfo table. It might not be there.
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " +
-                            SubscriptionManager.IS_EMBEDDED + " INTEGER DEFAULT 0;");
+                            Telephony.SimInfo.COLUMN_IS_EMBEDDED + " INTEGER DEFAULT 0;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " +
-                            SubscriptionManager.ACCESS_RULES + " BLOB;");
+                            Telephony.SimInfo.COLUMN_ACCESS_RULES + " BLOB;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " +
-                            SubscriptionManager.IS_REMOVABLE + " INTEGER DEFAULT 0;");
+                            Telephony.SimInfo.COLUMN_IS_REMOVABLE + " INTEGER DEFAULT 0;");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -1039,18 +1122,18 @@
                 try {
                     // Try to update the siminfo table. It might not be there.
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.ENHANCED_4G_MODE_ENABLED
+                            + Telephony.SimInfo.COLUMN_ENHANCED_4G_MODE_ENABLED
                             + " INTEGER DEFAULT -1;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.VT_IMS_ENABLED + " INTEGER DEFAULT -1;");
+                            + Telephony.SimInfo.COLUMN_VT_IMS_ENABLED + " INTEGER DEFAULT -1;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.WFC_IMS_ENABLED + " INTEGER DEFAULT -1;");
+                            + Telephony.SimInfo.COLUMN_WFC_IMS_ENABLED + " INTEGER DEFAULT -1;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.WFC_IMS_MODE + " INTEGER DEFAULT -1;");
+                            + Telephony.SimInfo.COLUMN_WFC_IMS_MODE + " INTEGER DEFAULT -1;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.WFC_IMS_ROAMING_MODE + " INTEGER DEFAULT -1;");
+                            + Telephony.SimInfo.COLUMN_WFC_IMS_ROAMING_MODE + " INTEGER DEFAULT -1;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.WFC_IMS_ROAMING_ENABLED + " INTEGER DEFAULT -1;");
+                            + Telephony.SimInfo.COLUMN_WFC_IMS_ROAMING_ENABLED + " INTEGER DEFAULT -1;");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + CARRIERS_TABLE + " upgrade. " +
@@ -1094,17 +1177,17 @@
                 // of the new column SubscriptionManager.CARD_ID, and replace the SIMINFO_TABLE with
                 // the new table.
                 Cursor c = null;
-                String[] proj = {SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID};
+                String[] proj = {Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID};
                 recreateSimInfoDB(c, db, proj);
                 if (VDBG) {
                     c = db.query(SIMINFO_TABLE, proj, null, null, null, null, null);
                     log("dbh.onUpgrade:- after upgrading " + SIMINFO_TABLE
                             + " total number of rows: " + c.getCount());
                     c.close();
-                    c = db.query(SIMINFO_TABLE, proj, SubscriptionManager.CARD_ID + " IS NOT NULL",
-                            null, null, null, null);
+                    c = db.query(SIMINFO_TABLE, proj, Telephony.SimInfo.COLUMN_CARD_ID
+                                    + " IS NOT NULL", null, null, null, null);
                     log("dbh.onUpgrade:- after upgrading total number of rows with "
-                            + SubscriptionManager.CARD_ID + ": " + c.getCount());
+                            + Telephony.SimInfo.COLUMN_CARD_ID + ": " + c.getCount());
                     c.close();
                 }
                 oldVersion = 25 << 16 | 6;
@@ -1130,9 +1213,9 @@
                 try {
                     // Try to update the siminfo table. It might not be there.
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE +
-                            " ADD COLUMN " + SubscriptionManager.MCC_STRING + " TEXT;");
+                            " ADD COLUMN " + Telephony.SimInfo.COLUMN_MCC_STRING + " TEXT;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE +
-                            " ADD COLUMN " + SubscriptionManager.MNC_STRING + " TEXT;");
+                            " ADD COLUMN " + Telephony.SimInfo.COLUMN_MNC_STRING + " TEXT;");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -1140,8 +1223,8 @@
                     }
                 }
                 // Migrate the old integer values over to strings
-                String[] proj = {SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID,
-                        SubscriptionManager.MCC, SubscriptionManager.MNC};
+                String[] proj = {Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID,
+                        Telephony.SimInfo.COLUMN_MCC, Telephony.SimInfo.COLUMN_MNC};
                 try (Cursor c = db.query(SIMINFO_TABLE, proj, null, null, null, null, null)) {
                     while (c.moveToNext()) {
                         fillInMccMncStringAtCursor(mContext, db, c);
@@ -1154,7 +1237,7 @@
                 try {
                     // Try to update the siminfo table. It might not be there.
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.IS_OPPORTUNISTIC + " INTEGER DEFAULT 0;");
+                            + Telephony.SimInfo.COLUMN_IS_OPPORTUNISTIC + " INTEGER DEFAULT 0;");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -1184,7 +1267,7 @@
                 try {
                     // Try to update the siminfo table. It might not be there.
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                        + SubscriptionManager.GROUP_UUID + " TEXT;");
+                        + Telephony.SimInfo.COLUMN_GROUP_UUID + " TEXT;");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -1198,7 +1281,7 @@
                 try {
                     // Try to update the siminfo table. It might not be there.
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.IS_METERED + " INTEGER DEFAULT 1;");
+                            + Telephony.SimInfo.COLUMN_IS_METERED + " INTEGER DEFAULT 1;");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -1212,7 +1295,7 @@
                 try {
                     // Try to update the siminfo table. It might not be there.
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.ISO_COUNTRY_CODE + " TEXT;");
+                            + Telephony.SimInfo.COLUMN_ISO_COUNTRY_CODE + " TEXT;");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -1226,7 +1309,7 @@
                 try {
                     // Try to update the siminfo table. It might not be there.
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.CARRIER_ID + " INTEGER DEFAULT -1;");
+                            + Telephony.SimInfo.COLUMN_CARRIER_ID + " INTEGER DEFAULT -1;");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -1240,8 +1323,8 @@
                 try {
                     // Try to update the siminfo table. It might not be there.
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " +
-                            SubscriptionManager.PROFILE_CLASS + " INTEGER DEFAULT " +
-                            SubscriptionManager.PROFILE_CLASS_DEFAULT + ";");
+                            Telephony.SimInfo.COLUMN_PROFILE_CLASS + " INTEGER DEFAULT " +
+                            Telephony.SimInfo.PROFILE_CLASS_UNSET + ";");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -1255,8 +1338,8 @@
                 try {
                     // Try to update the siminfo table. It might not be there.
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                        + SubscriptionManager.SUBSCRIPTION_TYPE + " INTEGER DEFAULT "
-                        + SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM + ";");
+                        + Telephony.SimInfo.COLUMN_SUBSCRIPTION_TYPE + " INTEGER DEFAULT "
+                        + Telephony.SimInfo.SUBSCRIPTION_TYPE_LOCAL_SIM + ";");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -1282,13 +1365,13 @@
             }
 
             if (oldVersion < (37 << 16 | 6)) {
-                // Add new columns SubscriptionManager.EHPLMNS and SubscriptionManager.HPLMNS into
+                // Add new columns Telephony.SimInfo.EHPLMNS and Telephony.SimInfo.HPLMNS into
                 // the database.
                 try {
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE +
-                            " ADD COLUMN " + SubscriptionManager.EHPLMNS + " TEXT;");
+                            " ADD COLUMN " + Telephony.SimInfo.COLUMN_EHPLMNS + " TEXT;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE +
-                            " ADD COLUMN " + SubscriptionManager.HPLMNS + " TEXT;");
+                            " ADD COLUMN " + Telephony.SimInfo.COLUMN_HPLMNS + " TEXT;");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade for ehplmns. " +
@@ -1298,25 +1381,11 @@
                 oldVersion = 37 << 16 | 6;
             }
 
-            if (oldVersion < (38 << 16 | 6)) {
-                try {
-                    // Try to update the siminfo table. It might not be there.
-                    db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.WHITE_LISTED_APN_DATA + " INTEGER DEFAULT 0;");
-                } catch (SQLiteException e) {
-                    if (DBG) {
-                        log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
-                                "The table will get created in onOpen.");
-                    }
-                }
-                oldVersion = 38 << 16 | 6;
-            }
-
             if (oldVersion < (39 << 16 | 6)) {
                 try {
                     // Try to update the siminfo table. It might not be there.
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.GROUP_OWNER + " TEXT;");
+                            + Telephony.SimInfo.COLUMN_GROUP_OWNER + " TEXT;");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -1330,7 +1399,7 @@
                 try {
                     // Try to update the siminfo table. It might not be there.
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.DATA_ENABLED_OVERRIDE_RULES + " TEXT;");
+                            + Telephony.SimInfo.COLUMN_DATA_ENABLED_OVERRIDE_RULES + " TEXT;");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -1344,7 +1413,7 @@
                 try {
                     // Try to update the siminfo table. It might not be there.
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.IMSI + " TEXT;");
+                            + Telephony.SimInfo.COLUMN_IMSI + " TEXT;");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -1358,7 +1427,7 @@
                 try {
                     // Try to update the siminfo table. It might not be there.
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " +
-                        SubscriptionManager.ACCESS_RULES_FROM_CARRIER_CONFIGS + " BLOB;");
+                            Telephony.SimInfo.COLUMN_ACCESS_RULES_FROM_CARRIER_CONFIGS + " BLOB;");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -1367,6 +1436,50 @@
                 }
             }
 
+            if (oldVersion < (43 << 16 | 6)) {
+                try {
+                    // Try to update the siminfo table. It might not be there.
+                    db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
+                            + Telephony.SimInfo.COLUMN_UICC_APPLICATIONS_ENABLED
+                            + " INTEGER DEFAULT 1;");
+                } catch (SQLiteException e) {
+                    if (DBG) {
+                        log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
+                                "The table will get created in onOpen.");
+                    }
+                }
+                oldVersion = 43 << 16 | 6;
+            }
+
+            if (oldVersion < (44 << 16 | 6)) {
+                try {
+                    // Try to update the siminfo table. It might not be there.
+                    db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
+                            + Telephony.SimInfo.COLUMN_ALLOWED_NETWORK_TYPES
+                            + " BIGINT DEFAULT -1;");
+                } catch (SQLiteException e) {
+                    if (DBG) {
+                        log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
+                                "The table will get created in onOpen.");
+                    }
+                }
+                oldVersion = 44 << 16 | 6;
+            }
+
+            if (oldVersion < (45 << 16 | 6)) {
+                try {
+                    // Try to update the siminfo table. It might not be there.
+                    db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
+                            + Telephony.SimInfo.COLUMN_IMS_RCS_UCE_ENABLED
+                            + " INTEGER DEFAULT 0;");
+                } catch (SQLiteException e) {
+                    if (DBG) {
+                        log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
+                                "The table will get created in onOpen.");
+                    }
+                }
+                oldVersion = 45 << 16 | 6;
+            }
 
             if (DBG) {
                 log("dbh.onUpgrade:- db=" + db + " oldV=" + oldVersion + " newV=" + newVersion);
@@ -1431,51 +1544,51 @@
 
         private void copySimInfoValuesV24(ContentValues cv, Cursor c) {
             // String vals
-            getStringValueFromCursor(cv, c, SubscriptionManager.ICC_ID);
-            getStringValueFromCursor(cv, c, SubscriptionManager.DISPLAY_NAME);
-            getStringValueFromCursor(cv, c, SubscriptionManager.CARRIER_NAME);
-            getStringValueFromCursor(cv, c, SubscriptionManager.NUMBER);
+            getStringValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_ICC_ID);
+            getStringValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_DISPLAY_NAME);
+            getStringValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CARRIER_NAME);
+            getStringValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_NUMBER);
 
             // bool/int vals
-            getIntValueFromCursor(cv, c, SubscriptionManager.SIM_SLOT_INDEX);
-            getIntValueFromCursor(cv, c, SubscriptionManager.NAME_SOURCE);
-            getIntValueFromCursor(cv, c, SubscriptionManager.COLOR);
-            getIntValueFromCursor(cv, c, SubscriptionManager.DISPLAY_NUMBER_FORMAT);
-            getIntValueFromCursor(cv, c, SubscriptionManager.DATA_ROAMING);
-            getIntValueFromCursor(cv, c, SubscriptionManager.MCC);
-            getIntValueFromCursor(cv, c, SubscriptionManager.MNC);
-            getIntValueFromCursor(cv, c, SubscriptionManager.SIM_PROVISIONING_STATUS);
-            getIntValueFromCursor(cv, c, SubscriptionManager.IS_EMBEDDED);
-            getIntValueFromCursor(cv, c, SubscriptionManager.IS_REMOVABLE);
-            getIntValueFromCursor(cv, c, SubscriptionManager.CB_EXTREME_THREAT_ALERT);
-            getIntValueFromCursor(cv, c, SubscriptionManager.CB_SEVERE_THREAT_ALERT);
-            getIntValueFromCursor(cv, c, SubscriptionManager.CB_AMBER_ALERT);
-            getIntValueFromCursor(cv, c, SubscriptionManager.CB_EMERGENCY_ALERT);
-            getIntValueFromCursor(cv, c, SubscriptionManager.CB_ALERT_SOUND_DURATION);
-            getIntValueFromCursor(cv, c, SubscriptionManager.CB_ALERT_REMINDER_INTERVAL);
-            getIntValueFromCursor(cv, c, SubscriptionManager.CB_ALERT_VIBRATE);
-            getIntValueFromCursor(cv, c, SubscriptionManager.CB_ALERT_SPEECH);
-            getIntValueFromCursor(cv, c, SubscriptionManager.CB_ETWS_TEST_ALERT);
-            getIntValueFromCursor(cv, c, SubscriptionManager.CB_CHANNEL_50_ALERT);
-            getIntValueFromCursor(cv, c, SubscriptionManager.CB_CMAS_TEST_ALERT);
-            getIntValueFromCursor(cv, c, SubscriptionManager.CB_OPT_OUT_DIALOG);
-            getIntValueFromCursor(cv, c, SubscriptionManager.ENHANCED_4G_MODE_ENABLED);
-            getIntValueFromCursor(cv, c, SubscriptionManager.VT_IMS_ENABLED);
-            getIntValueFromCursor(cv, c, SubscriptionManager.WFC_IMS_ENABLED);
-            getIntValueFromCursor(cv, c, SubscriptionManager.WFC_IMS_MODE);
-            getIntValueFromCursor(cv, c, SubscriptionManager.WFC_IMS_ROAMING_MODE);
-            getIntValueFromCursor(cv, c, SubscriptionManager.WFC_IMS_ROAMING_ENABLED);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_SIM_SLOT_INDEX);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_NAME_SOURCE);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_COLOR);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_DISPLAY_NUMBER_FORMAT);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_DATA_ROAMING);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_MCC);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_MNC);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_SIM_PROVISIONING_STATUS);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_IS_EMBEDDED);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_IS_REMOVABLE);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_EXTREME_THREAT_ALERT);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_SEVERE_THREAT_ALERT);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_AMBER_ALERT);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_EMERGENCY_ALERT);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_ALERT_SOUND_DURATION);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_ALERT_REMINDER_INTERVAL);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_ALERT_VIBRATE);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_ALERT_SPEECH);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_ETWS_TEST_ALERT);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_CHANNEL_50_ALERT);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_CMAS_TEST_ALERT);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_OPT_OUT_DIALOG);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_ENHANCED_4G_MODE_ENABLED);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_VT_IMS_ENABLED);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_WFC_IMS_ENABLED);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_WFC_IMS_MODE);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_WFC_IMS_ROAMING_MODE);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_WFC_IMS_ROAMING_ENABLED);
 
             // Blob vals
-            getBlobValueFromCursor(cv, c, SubscriptionManager.ACCESS_RULES);
+            getBlobValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_ACCESS_RULES);
         }
 
         private void getCardIdfromIccid(ContentValues cv, Cursor c) {
-            int columnIndex = c.getColumnIndex(SubscriptionManager.ICC_ID);
+            int columnIndex = c.getColumnIndex(Telephony.SimInfo.COLUMN_ICC_ID);
             if (columnIndex != -1) {
                 String fromCursor = c.getString(columnIndex);
                 if (!TextUtils.isEmpty(fromCursor)) {
-                    cv.put(SubscriptionManager.CARD_ID, fromCursor);
+                    cv.put(Telephony.SimInfo.COLUMN_CARD_ID, fromCursor);
                 }
             }
         }
@@ -1824,13 +1937,11 @@
                         // Change bearer to a bitmask
                         String bearerStr = c.getString(c.getColumnIndex(BEARER));
                         if (!TextUtils.isEmpty(bearerStr)) {
-                            int bearer_bitmask = ServiceState.getBitmaskForTech(
-                                    Integer.parseInt(bearerStr));
+                            int bearer_bitmask = getBitmaskForTech(Integer.parseInt(bearerStr));
                             cv.put(BEARER_BITMASK, bearer_bitmask);
 
-                            int networkTypeBitmask = ServiceState.getBitmaskForTech(
-                                    ServiceState.rilRadioTechnologyToNetworkType(
-                                            Integer.parseInt(bearerStr)));
+                            int networkTypeBitmask = rilRadioTechnologyToNetworkTypeBitmask(
+                                    Integer.parseInt(bearerStr));
                             cv.put(NETWORK_TYPE_BITMASK, networkTypeBitmask);
                         }
 
@@ -1878,7 +1989,7 @@
                                         e + " for cv " + cv);
                             // Insertion failed which could be due to a conflict. Check if that is
                             // the case and merge the entries
-                            Cursor oldRow = DatabaseHelper.selectConflictingRow(db,
+                            Cursor oldRow = selectConflictingRow(db,
                                     CARRIERS_TABLE_TMP, cv);
                             if (oldRow != null) {
                                 ContentValues mergedValues = new ContentValues();
@@ -1918,8 +2029,7 @@
                 String fromCursor = c.getString(columnIndex);
                 if (!TextUtils.isEmpty(fromCursor) && fromCursor.matches("\\d+")) {
                     int networkBitmask = Integer.valueOf(fromCursor);
-                    int bearerBitmask = ServiceState.convertNetworkTypeBitmaskToBearerBitmask(
-                            networkBitmask);
+                    int bearerBitmask = convertNetworkTypeBitmaskToBearerBitmask(networkBitmask);
                     cv.put(BEARER_BITMASK, String.valueOf(bearerBitmask));
                 }
                 return;
@@ -1929,8 +2039,7 @@
                 String fromCursor = c.getString(columnIndex);
                 if (!TextUtils.isEmpty(fromCursor) && fromCursor.matches("\\d+")) {
                     int bearerBitmask = Integer.valueOf(fromCursor);
-                    int networkBitmask = ServiceState.convertBearerBitmaskToNetworkTypeBitmask(
-                            bearerBitmask);
+                    int networkBitmask = convertBearerBitmaskToNetworkTypeBitmask(bearerBitmask);
                     cv.put(NETWORK_TYPE_BITMASK, String.valueOf(networkBitmask));
                 }
             }
@@ -2022,22 +2131,20 @@
             int networkTypeBitmask = 0;
             String networkTypeList = parser.getAttributeValue(null, "network_type_bitmask");
             if (networkTypeList != null) {
-                networkTypeBitmask = ServiceState.getBitmaskFromString(networkTypeList);
+                networkTypeBitmask = getBitmaskFromString(networkTypeList);
             }
             map.put(NETWORK_TYPE_BITMASK, networkTypeBitmask);
 
             int bearerBitmask = 0;
             if (networkTypeList != null) {
-                bearerBitmask =
-                        ServiceState.convertNetworkTypeBitmaskToBearerBitmask(networkTypeBitmask);
+                bearerBitmask = convertNetworkTypeBitmaskToBearerBitmask(networkTypeBitmask);
             } else {
                 String bearerList = parser.getAttributeValue(null, "bearer_bitmask");
                 if (bearerList != null) {
-                    bearerBitmask = ServiceState.getBitmaskFromString(bearerList);
+                    bearerBitmask = getBitmaskFromString(bearerList);
                 }
                 // Update the network type bitmask to keep them sync.
-                networkTypeBitmask = ServiceState.convertBearerBitmaskToNetworkTypeBitmask(
-                        bearerBitmask);
+                networkTypeBitmask = convertBearerBitmaskToNetworkTypeBitmask(bearerBitmask);
                 map.put(NETWORK_TYPE_BITMASK, networkTypeBitmask);
             }
             map.put(BEARER_BITMASK, bearerBitmask);
@@ -2111,15 +2218,6 @@
             }
         }
 
-        static public ContentValues setDefaultValue(ContentValues values) {
-            if (!values.containsKey(SUBSCRIPTION_ID)) {
-                int subId = SubscriptionManager.getDefaultSubscriptionId();
-                values.put(SUBSCRIPTION_ID, subId);
-            }
-
-            return values;
-        }
-
         private void insertAddingDefaults(SQLiteDatabase db, ContentValues row) {
             row = setDefaultValue(row);
             try {
@@ -2162,264 +2260,264 @@
                 }
             }
         }
+    }
 
-        public static void mergeFieldsAndUpdateDb(SQLiteDatabase db, String table, Cursor oldRow,
-                                                  ContentValues newRow, ContentValues mergedValues,
-                                                  boolean onUpgrade, Context context) {
-            if (newRow.containsKey(TYPE)) {
-                // Merge the types
-                String oldType = oldRow.getString(oldRow.getColumnIndex(TYPE));
-                String newType = newRow.getAsString(TYPE);
+    public static void mergeFieldsAndUpdateDb(SQLiteDatabase db, String table, Cursor oldRow,
+            ContentValues newRow, ContentValues mergedValues,
+            boolean onUpgrade, Context context) {
+        if (newRow.containsKey(TYPE)) {
+            // Merge the types
+            String oldType = oldRow.getString(oldRow.getColumnIndex(TYPE));
+            String newType = newRow.getAsString(TYPE);
 
-                if (!oldType.equalsIgnoreCase(newType)) {
-                    if (oldType.equals("") || newType.equals("")) {
-                        newRow.put(TYPE, "");
-                    } else {
-                        String[] oldTypes = oldType.toLowerCase().split(",");
-                        String[] newTypes = newType.toLowerCase().split(",");
+            if (!oldType.equalsIgnoreCase(newType)) {
+                if (oldType.equals("") || newType.equals("")) {
+                    newRow.put(TYPE, "");
+                } else {
+                    String[] oldTypes = oldType.toLowerCase().split(",");
+                    String[] newTypes = newType.toLowerCase().split(",");
 
-                        if (VDBG) {
-                            log("mergeFieldsAndUpdateDb: Calling separateRowsNeeded() oldType=" +
-                                    oldType + " old bearer=" + oldRow.getInt(oldRow.getColumnIndex(
-                                    BEARER_BITMASK)) +  " old networkType=" +
-                                    oldRow.getInt(oldRow.getColumnIndex(NETWORK_TYPE_BITMASK)) +
-                                    " old profile_id=" + oldRow.getInt(oldRow.getColumnIndex(
-                                    PROFILE_ID)) + " newRow " + newRow);
-                        }
-
-                        // If separate rows are needed, do not need to merge any further
-                        if (separateRowsNeeded(db, table, oldRow, newRow, context, oldTypes,
-                                newTypes)) {
-                            if (VDBG) log("mergeFieldsAndUpdateDb: separateRowsNeeded() returned " +
-                                    "true");
-                            return;
-                        }
-
-                        // Merge the 2 types
-                        ArrayList<String> mergedTypes = new ArrayList<String>();
-                        mergedTypes.addAll(Arrays.asList(oldTypes));
-                        for (String s : newTypes) {
-                            if (!mergedTypes.contains(s.trim())) {
-                                mergedTypes.add(s);
-                            }
-                        }
-                        StringBuilder mergedType = new StringBuilder();
-                        for (int i = 0; i < mergedTypes.size(); i++) {
-                            mergedType.append((i == 0 ? "" : ",") + mergedTypes.get(i));
-                        }
-                        newRow.put(TYPE, mergedType.toString());
+                    if (VDBG) {
+                        log("mergeFieldsAndUpdateDb: Calling separateRowsNeeded() oldType=" +
+                                oldType + " old bearer=" + oldRow.getInt(oldRow.getColumnIndex(
+                                BEARER_BITMASK)) +  " old networkType=" +
+                                oldRow.getInt(oldRow.getColumnIndex(NETWORK_TYPE_BITMASK)) +
+                                " old profile_id=" + oldRow.getInt(oldRow.getColumnIndex(
+                                PROFILE_ID)) + " newRow " + newRow);
                     }
-                }
-                mergedValues.put(TYPE, newRow.getAsString(TYPE));
-            }
 
-            if (newRow.containsKey(BEARER_BITMASK)) {
-                int oldBearer = oldRow.getInt(oldRow.getColumnIndex(BEARER_BITMASK));
-                int newBearer = newRow.getAsInteger(BEARER_BITMASK);
-                if (oldBearer != newBearer) {
-                    if (oldBearer == 0 || newBearer == 0) {
-                        newRow.put(BEARER_BITMASK, 0);
-                    } else {
-                        newRow.put(BEARER_BITMASK, (oldBearer | newBearer));
+                    // If separate rows are needed, do not need to merge any further
+                    if (separateRowsNeeded(db, table, oldRow, newRow, context, oldTypes,
+                            newTypes)) {
+                        if (VDBG) log("mergeFieldsAndUpdateDb: separateRowsNeeded() returned " +
+                                "true");
+                        return;
                     }
-                }
-                mergedValues.put(BEARER_BITMASK, newRow.getAsInteger(BEARER_BITMASK));
-            }
 
-            if (newRow.containsKey(NETWORK_TYPE_BITMASK)) {
-                int oldBitmask = oldRow.getInt(oldRow.getColumnIndex(NETWORK_TYPE_BITMASK));
-                int newBitmask = newRow.getAsInteger(NETWORK_TYPE_BITMASK);
-                if (oldBitmask != newBitmask) {
-                    if (oldBitmask == 0 || newBitmask == 0) {
-                        newRow.put(NETWORK_TYPE_BITMASK, 0);
-                    } else {
-                        newRow.put(NETWORK_TYPE_BITMASK, (oldBitmask | newBitmask));
+                    // Merge the 2 types
+                    ArrayList<String> mergedTypes = new ArrayList<String>();
+                    mergedTypes.addAll(Arrays.asList(oldTypes));
+                    for (String s : newTypes) {
+                        if (!mergedTypes.contains(s.trim())) {
+                            mergedTypes.add(s);
+                        }
                     }
-                }
-                mergedValues.put(NETWORK_TYPE_BITMASK, newRow.getAsInteger(NETWORK_TYPE_BITMASK));
-            }
-
-            if (newRow.containsKey(BEARER_BITMASK)
-                    && newRow.containsKey(NETWORK_TYPE_BITMASK)) {
-                syncBearerBitmaskAndNetworkTypeBitmask(mergedValues);
-            }
-
-            if (!onUpgrade) {
-                // Do not overwrite a carrier or user edit with EDITED=UNEDITED
-                if (newRow.containsKey(EDITED_STATUS)) {
-                    int oldEdited = oldRow.getInt(oldRow.getColumnIndex(EDITED_STATUS));
-                    int newEdited = newRow.getAsInteger(EDITED_STATUS);
-                    if (newEdited == UNEDITED && (oldEdited == CARRIER_EDITED
-                                || oldEdited == CARRIER_DELETED
-                                || oldEdited == CARRIER_DELETED_BUT_PRESENT_IN_XML
-                                || oldEdited == USER_EDITED
-                                || oldEdited == USER_DELETED
-                                || oldEdited == USER_DELETED_BUT_PRESENT_IN_XML)) {
-                        newRow.remove(EDITED_STATUS);
+                    StringBuilder mergedType = new StringBuilder();
+                    for (int i = 0; i < mergedTypes.size(); i++) {
+                        mergedType.append((i == 0 ? "" : ",") + mergedTypes.get(i));
                     }
+                    newRow.put(TYPE, mergedType.toString());
                 }
-                mergedValues.putAll(newRow);
             }
-
-            if (mergedValues.size() > 0) {
-                db.update(table, mergedValues, "_id=" + oldRow.getInt(oldRow.getColumnIndex("_id")),
-                        null);
-            }
+            mergedValues.put(TYPE, newRow.getAsString(TYPE));
         }
 
-        private static boolean separateRowsNeeded(SQLiteDatabase db, String table, Cursor oldRow,
-                                                  ContentValues newRow, Context context,
-                                                  String[] oldTypes, String[] newTypes) {
-            // If this APN falls under persist_apns_for_plmn, and the
-            // only difference between old type and new type is that one has dun, and
-            // the APNs have profile_id 0 or not set, then set the profile_id to 1 for
-            // the dun APN/remove dun from type. This will ensure both oldRow and newRow exist
-            // separately in db.
-
-            boolean match = false;
-
-            // Check if APN falls under persist_apns_for_plmn
-            if (context.getResources() != null) {
-                String[] persistApnsForPlmns = context.getResources().getStringArray(
-                        R.array.persist_apns_for_plmn);
-                for (String s : persistApnsForPlmns) {
-                    if (s.equalsIgnoreCase(newRow.getAsString(NUMERIC))) {
-                        match = true;
-                        break;
-                    }
+        if (newRow.containsKey(BEARER_BITMASK)) {
+            int oldBearer = oldRow.getInt(oldRow.getColumnIndex(BEARER_BITMASK));
+            int newBearer = newRow.getAsInteger(BEARER_BITMASK);
+            if (oldBearer != newBearer) {
+                if (oldBearer == 0 || newBearer == 0) {
+                    newRow.put(BEARER_BITMASK, 0);
+                } else {
+                    newRow.put(BEARER_BITMASK, (oldBearer | newBearer));
                 }
-            } else {
-                loge("separateRowsNeeded: resources=null");
+            }
+            mergedValues.put(BEARER_BITMASK, newRow.getAsInteger(BEARER_BITMASK));
+        }
+
+        if (newRow.containsKey(NETWORK_TYPE_BITMASK)) {
+            int oldBitmask = oldRow.getInt(oldRow.getColumnIndex(NETWORK_TYPE_BITMASK));
+            int newBitmask = newRow.getAsInteger(NETWORK_TYPE_BITMASK);
+            if (oldBitmask != newBitmask) {
+                if (oldBitmask == 0 || newBitmask == 0) {
+                    newRow.put(NETWORK_TYPE_BITMASK, 0);
+                } else {
+                    newRow.put(NETWORK_TYPE_BITMASK, (oldBitmask | newBitmask));
+                }
+            }
+            mergedValues.put(NETWORK_TYPE_BITMASK, newRow.getAsInteger(NETWORK_TYPE_BITMASK));
+        }
+
+        if (newRow.containsKey(BEARER_BITMASK)
+                && newRow.containsKey(NETWORK_TYPE_BITMASK)) {
+            syncBearerBitmaskAndNetworkTypeBitmask(mergedValues);
+        }
+
+        if (!onUpgrade) {
+            // Do not overwrite a carrier or user edit with EDITED=UNEDITED
+            if (newRow.containsKey(EDITED_STATUS)) {
+                int oldEdited = oldRow.getInt(oldRow.getColumnIndex(EDITED_STATUS));
+                int newEdited = newRow.getAsInteger(EDITED_STATUS);
+                if (newEdited == UNEDITED && (oldEdited == CARRIER_EDITED
+                        || oldEdited == CARRIER_DELETED
+                        || oldEdited == CARRIER_DELETED_BUT_PRESENT_IN_XML
+                        || oldEdited == USER_EDITED
+                        || oldEdited == USER_DELETED
+                        || oldEdited == USER_DELETED_BUT_PRESENT_IN_XML)) {
+                    newRow.remove(EDITED_STATUS);
+                }
+            }
+            mergedValues.putAll(newRow);
+        }
+
+        if (mergedValues.size() > 0) {
+            db.update(table, mergedValues, "_id=" + oldRow.getInt(oldRow.getColumnIndex("_id")),
+                    null);
+        }
+    }
+
+    private static boolean separateRowsNeeded(SQLiteDatabase db, String table, Cursor oldRow,
+            ContentValues newRow, Context context,
+            String[] oldTypes, String[] newTypes) {
+        // If this APN falls under persist_apns_for_plmn, and the
+        // only difference between old type and new type is that one has dun, and
+        // the APNs have profile_id 0 or not set, then set the profile_id to 1 for
+        // the dun APN/remove dun from type. This will ensure both oldRow and newRow exist
+        // separately in db.
+
+        boolean match = false;
+
+        // Check if APN falls under persist_apns_for_plmn
+        if (context.getResources() != null) {
+            String[] persistApnsForPlmns = context.getResources().getStringArray(
+                    R.array.persist_apns_for_plmn);
+            for (String s : persistApnsForPlmns) {
+                if (s.equalsIgnoreCase(newRow.getAsString(NUMERIC))) {
+                    match = true;
+                    break;
+                }
+            }
+        } else {
+            loge("separateRowsNeeded: resources=null");
+        }
+
+        if (!match) return false;
+
+        // APN falls under persist_apns_for_plmn
+        // Check if only difference between old type and new type is that
+        // one has dun
+        ArrayList<String> oldTypesAl = new ArrayList<String>(Arrays.asList(oldTypes));
+        ArrayList<String> newTypesAl = new ArrayList<String>(Arrays.asList(newTypes));
+        ArrayList<String> listWithDun = null;
+        ArrayList<String> listWithoutDun = null;
+        boolean dunInOld = false;
+        if (oldTypesAl.size() == newTypesAl.size() + 1) {
+            listWithDun = oldTypesAl;
+            listWithoutDun = newTypesAl;
+            dunInOld = true;
+        } else if (oldTypesAl.size() + 1 == newTypesAl.size()) {
+            listWithDun = newTypesAl;
+            listWithoutDun = oldTypesAl;
+        } else {
+            return false;
+        }
+
+        if (listWithDun.contains("dun") && !listWithoutDun.contains("dun")) {
+            listWithoutDun.add("dun");
+            if (!listWithDun.containsAll(listWithoutDun)) {
+                return false;
             }
 
-            if (!match) return false;
-
-            // APN falls under persist_apns_for_plmn
-            // Check if only difference between old type and new type is that
+            // Only difference between old type and new type is that
             // one has dun
-            ArrayList<String> oldTypesAl = new ArrayList<String>(Arrays.asList(oldTypes));
-            ArrayList<String> newTypesAl = new ArrayList<String>(Arrays.asList(newTypes));
-            ArrayList<String> listWithDun = null;
-            ArrayList<String> listWithoutDun = null;
-            boolean dunInOld = false;
-            if (oldTypesAl.size() == newTypesAl.size() + 1) {
-                listWithDun = oldTypesAl;
-                listWithoutDun = newTypesAl;
-                dunInOld = true;
-            } else if (oldTypesAl.size() + 1 == newTypesAl.size()) {
-                listWithDun = newTypesAl;
-                listWithoutDun = oldTypesAl;
+            // Check if profile_id is 0/not set
+            if (oldRow.getInt(oldRow.getColumnIndex(PROFILE_ID)) == 0) {
+                if (dunInOld) {
+                    // Update oldRow to remove dun from its type field
+                    ContentValues updateOldRow = new ContentValues();
+                    StringBuilder sb = new StringBuilder();
+                    boolean first = true;
+                    for (String s : listWithDun) {
+                        if (!s.equalsIgnoreCase("dun")) {
+                            sb.append(first ? s : "," + s);
+                            first = false;
+                        }
+                    }
+                    String updatedType = sb.toString();
+                    if (VDBG) {
+                        log("separateRowsNeeded: updating type in oldRow to " + updatedType);
+                    }
+                    updateOldRow.put(TYPE, updatedType);
+                    db.update(table, updateOldRow,
+                            "_id=" + oldRow.getInt(oldRow.getColumnIndex("_id")), null);
+                    return true;
+                } else {
+                    if (VDBG) log("separateRowsNeeded: adding profile id 1 to newRow");
+                    // Update newRow to set profile_id to 1
+                    newRow.put(PROFILE_ID, new Integer(1));
+                }
             } else {
                 return false;
             }
 
-            if (listWithDun.contains("dun") && !listWithoutDun.contains("dun")) {
-                listWithoutDun.add("dun");
-                if (!listWithDun.containsAll(listWithoutDun)) {
-                    return false;
-                }
-
-                // Only difference between old type and new type is that
-                // one has dun
-                // Check if profile_id is 0/not set
-                if (oldRow.getInt(oldRow.getColumnIndex(PROFILE_ID)) == 0) {
-                    if (dunInOld) {
-                        // Update oldRow to remove dun from its type field
-                        ContentValues updateOldRow = new ContentValues();
-                        StringBuilder sb = new StringBuilder();
-                        boolean first = true;
-                        for (String s : listWithDun) {
-                            if (!s.equalsIgnoreCase("dun")) {
-                                sb.append(first ? s : "," + s);
-                                first = false;
-                            }
-                        }
-                        String updatedType = sb.toString();
-                        if (VDBG) {
-                            log("separateRowsNeeded: updating type in oldRow to " + updatedType);
-                        }
-                        updateOldRow.put(TYPE, updatedType);
-                        db.update(table, updateOldRow,
-                                "_id=" + oldRow.getInt(oldRow.getColumnIndex("_id")), null);
-                        return true;
-                    } else {
-                        if (VDBG) log("separateRowsNeeded: adding profile id 1 to newRow");
-                        // Update newRow to set profile_id to 1
-                        newRow.put(PROFILE_ID, new Integer(1));
-                    }
-                } else {
-                    return false;
-                }
-
-                // If match was found, both oldRow and newRow need to exist
-                // separately in db. Add newRow to db.
-                try {
-                    db.insertWithOnConflict(table, null, newRow, SQLiteDatabase.CONFLICT_REPLACE);
-                    if (VDBG) log("separateRowsNeeded: added newRow with profile id 1 to db");
-                    return true;
-                } catch (SQLException e) {
-                    loge("Exception on trying to add new row after updating profile_id");
-                }
+            // If match was found, both oldRow and newRow need to exist
+            // separately in db. Add newRow to db.
+            try {
+                db.insertWithOnConflict(table, null, newRow, SQLiteDatabase.CONFLICT_REPLACE);
+                if (VDBG) log("separateRowsNeeded: added newRow with profile id 1 to db");
+                return true;
+            } catch (SQLException e) {
+                loge("Exception on trying to add new row after updating profile_id");
             }
-
-            return false;
         }
 
-        public static Cursor selectConflictingRow(SQLiteDatabase db, String table,
-                                                  ContentValues row) {
-            // Conflict is possible only when numeric, mcc, mnc (fields without any default value)
-            // are set in the new row
-            if (!row.containsKey(NUMERIC) || !row.containsKey(MCC) || !row.containsKey(MNC)) {
-                loge("dbh.selectConflictingRow: called for non-conflicting row: " + row);
-                return null;
-            }
+        return false;
+    }
 
-            String[] columns = { "_id",
-                    TYPE,
-                    EDITED_STATUS,
-                    BEARER_BITMASK,
-                    NETWORK_TYPE_BITMASK,
-                    PROFILE_ID };
-            String selection = TextUtils.join("=? AND ", CARRIERS_UNIQUE_FIELDS) + "=?";
-            int i = 0;
-            String[] selectionArgs = new String[CARRIERS_UNIQUE_FIELDS.size()];
-            for (String field : CARRIERS_UNIQUE_FIELDS) {
-                if (!row.containsKey(field)) {
-                    selectionArgs[i++] = CARRIERS_UNIQUE_FIELDS_DEFAULTS.get(field);
-                } else {
-                    if (CARRIERS_BOOLEAN_FIELDS.contains(field)) {
-                        // for boolean fields we overwrite the strings "true" and "false" with "1"
-                        // and "0"
-                        selectionArgs[i++] = convertStringToIntString(row.getAsString(field));
-                    } else {
-                        selectionArgs[i++] = row.getAsString(field);
-                    }
-                }
-            }
-
-            Cursor c = db.query(table, columns, selection, selectionArgs, null, null, null);
-
-            if (c != null) {
-                if (c.getCount() == 1) {
-                    if (VDBG) log("dbh.selectConflictingRow: " + c.getCount() + " conflicting " +
-                            "row found");
-                    if (c.moveToFirst()) {
-                        return c;
-                    } else {
-                        loge("dbh.selectConflictingRow: moveToFirst() failed");
-                    }
-                } else {
-                    loge("dbh.selectConflictingRow: Expected 1 but found " + c.getCount() +
-                            " matching rows found for cv " + row);
-                }
-                c.close();
-            } else {
-                loge("dbh.selectConflictingRow: Error - c is null; no matching row found for " +
-                        "cv " + row);
-            }
-
+    public static Cursor selectConflictingRow(SQLiteDatabase db, String table,
+            ContentValues row) {
+        // Conflict is possible only when numeric, mcc, mnc (fields without any default value)
+        // are set in the new row
+        if (!row.containsKey(NUMERIC) || !row.containsKey(MCC) || !row.containsKey(MNC)) {
+            loge("dbh.selectConflictingRow: called for non-conflicting row: " + row);
             return null;
         }
+
+        String[] columns = { "_id",
+                TYPE,
+                EDITED_STATUS,
+                BEARER_BITMASK,
+                NETWORK_TYPE_BITMASK,
+                PROFILE_ID };
+        String selection = TextUtils.join("=? AND ", CARRIERS_UNIQUE_FIELDS) + "=?";
+        int i = 0;
+        String[] selectionArgs = new String[CARRIERS_UNIQUE_FIELDS.size()];
+        for (String field : CARRIERS_UNIQUE_FIELDS) {
+            if (!row.containsKey(field)) {
+                selectionArgs[i++] = CARRIERS_UNIQUE_FIELDS_DEFAULTS.get(field);
+            } else {
+                if (CARRIERS_BOOLEAN_FIELDS.contains(field)) {
+                    // for boolean fields we overwrite the strings "true" and "false" with "1"
+                    // and "0"
+                    selectionArgs[i++] = convertStringToIntString(row.getAsString(field));
+                } else {
+                    selectionArgs[i++] = row.getAsString(field);
+                }
+            }
+        }
+
+        Cursor c = db.query(table, columns, selection, selectionArgs, null, null, null);
+
+        if (c != null) {
+            if (c.getCount() == 1) {
+                if (VDBG) log("dbh.selectConflictingRow: " + c.getCount() + " conflicting " +
+                        "row found");
+                if (c.moveToFirst()) {
+                    return c;
+                } else {
+                    loge("dbh.selectConflictingRow: moveToFirst() failed");
+                }
+            } else {
+                loge("dbh.selectConflictingRow: Expected 1 but found " + c.getCount() +
+                        " matching rows found for cv " + row);
+            }
+            c.close();
+        } else {
+            loge("dbh.selectConflictingRow: Error - c is null; no matching row found for " +
+                    "cv " + row);
+        }
+
+        return null;
     }
 
     /**
@@ -2479,6 +2577,7 @@
     private void restoreApnsWithService(int subId) {
         Context context = getContext();
         Resources r = context.getResources();
+        AtomicBoolean connectionBindingInvalid = new AtomicBoolean(false);
         ServiceConnection connection = new ServiceConnection() {
             @Override
             public void onServiceConnected(ComponentName className,
@@ -2497,6 +2596,24 @@
                     mIApnSourceService = null;
                 }
             }
+
+            @Override
+            public void onBindingDied(ComponentName name) {
+                loge("The binding to the apn service connection is dead: " + name);
+                synchronized (mLock) {
+                    connectionBindingInvalid.set(true);
+                    mLock.notifyAll();
+                }
+            }
+
+            @Override
+            public void onNullBinding(ComponentName name) {
+                loge("Null binding: " + name);
+                synchronized (mLock) {
+                    connectionBindingInvalid.set(true);
+                    mLock.notifyAll();
+                }
+            }
         };
 
         Intent intent = new Intent(IApnSourceService.class.getName());
@@ -2507,13 +2624,17 @@
             if (context.bindService(intent, connection, Context.BIND_IMPORTANT |
                         Context.BIND_AUTO_CREATE)) {
                 synchronized (mLock) {
-                    while (mIApnSourceService == null) {
+                    while (mIApnSourceService == null && !connectionBindingInvalid.get()) {
                         try {
                             mLock.wait();
                         } catch (InterruptedException e) {
                             loge("Error while waiting for service connection: " + e);
                         }
                     }
+                    if (connectionBindingInvalid.get()) {
+                        loge("The binding is invalid.");
+                        return;
+                    }
                     try {
                         ContentValues[] values = mIApnSourceService.getApns(subId);
                         if (values != null) {
@@ -2572,25 +2693,6 @@
 
         if (isNewBuild) {
             if (!apnSourceServiceExists(getContext())) {
-                // Call getReadableDatabase() to make sure onUpgrade is called
-                if (VDBG) log("onCreate: calling getReadableDatabase to trigger onUpgrade");
-                SQLiteDatabase db = getReadableDatabase();
-
-                // Get rid of old preferred apn shared preferences
-                SubscriptionManager sm = SubscriptionManager.from(getContext());
-                if (sm != null) {
-                    List<SubscriptionInfo> subInfoList = sm.getAllSubscriptionInfoList();
-                    for (SubscriptionInfo subInfo : subInfoList) {
-                        SharedPreferences spPrefFile = getContext().getSharedPreferences(
-                                PREF_FILE_APN + subInfo.getSubscriptionId(), Context.MODE_PRIVATE);
-                        if (spPrefFile != null) {
-                            SharedPreferences.Editor editor = spPrefFile.edit();
-                            editor.clear();
-                            editor.apply();
-                        }
-                    }
-                }
-
                 // Update APN DB
                 updateApnDb();
             }
@@ -2701,29 +2803,9 @@
         }
     }
 
-    private void deletePreferredApnId() {
-        SharedPreferences sp = getContext().getSharedPreferences(PREF_FILE_APN,
+    private void deletePreferredApnId(Context context) {
+        SharedPreferences sp = context.getSharedPreferences(PREF_FILE_APN,
                 Context.MODE_PRIVATE);
-
-        // Before deleting, save actual preferred apns (not the ids) in a separate SP.
-        // NOTE: This code to call setPreferredApn() can be removed since the function is now called
-        // from setPreferredApnId(). However older builds (pre oc-mr1) do not have that change, so
-        // when devices upgrade from those builds and this function is called, this code is needed
-        // otherwise the preferred APN will be lost.
-        Map<String, ?> allPrefApnId = sp.getAll();
-        for (String key : allPrefApnId.keySet()) {
-            // extract subId from key by removing COLUMN_APN_ID
-            try {
-                int subId = Integer.parseInt(key.replace(COLUMN_APN_ID, ""));
-                long apnId = getPreferredApnId(subId, false);
-                if (apnId != INVALID_APN_ID) {
-                    setPreferredApn(apnId, subId);
-                }
-            } catch (Exception e) {
-                loge("Skipping over key " + key + " due to exception " + e);
-            }
-        }
-
         SharedPreferences.Editor editor = sp.edit();
         editor.clear();
         editor.apply();
@@ -2764,19 +2846,27 @@
     private long getPreferredApnIdFromApn(int subId) {
         log("getPreferredApnIdFromApn: for subId " + subId);
         SQLiteDatabase db = getReadableDatabase();
-        String where = TextUtils.join("=? and ", CARRIERS_UNIQUE_FIELDS) + "=?";
-        String[] whereArgs = new String[CARRIERS_UNIQUE_FIELDS.size()];
+
+        List<String> whereList = new ArrayList<>();
+        List<String> whereArgsList = new ArrayList<>();
         SharedPreferences sp = getContext().getSharedPreferences(PREF_FILE_FULL_APN,
                 Context.MODE_PRIVATE);
-        long apnId = INVALID_APN_ID;
-        int i = 0;
         for (String key : CARRIERS_UNIQUE_FIELDS) {
-            whereArgs[i] = sp.getString(key + subId, null);
-            if (whereArgs[i] == null) {
-                return INVALID_APN_ID;
+            String value = sp.getString(key + subId, null);
+            if (value == null) {
+                continue;
+            } else {
+                whereList.add(key);
+                whereArgsList.add(value);
             }
-            i++;
         }
+        if (whereList.size() == 0) return INVALID_APN_ID;
+
+        String where = TextUtils.join("=? and ", whereList) + "=?";
+        String[] whereArgs = new String[whereArgsList.size()];
+        whereArgs = whereArgsList.toArray(whereArgs);
+
+        long apnId = INVALID_APN_ID;
         Cursor c = db.query(CARRIERS_TABLE, new String[]{"_id"}, where, whereArgs, null, null,
                 null);
         if (c != null) {
@@ -2825,8 +2915,6 @@
             String[] selectionArgs, String sort) {
         if (VDBG) log("query: url=" + url + ", projectionIn=" + projectionIn + ", selection="
                 + selection + "selectionArgs=" + selectionArgs + ", sort=" + sort);
-        TelephonyManager mTelephonyManager =
-                (TelephonyManager)getContext().getSystemService(Context.TELEPHONY_SERVICE);
         int subId = SubscriptionManager.getDefaultSubscriptionId();
         String subIdString;
         SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
@@ -2836,7 +2924,7 @@
         List<String> constraints = new ArrayList<String>();
 
         int match = s_urlMatcher.match(url);
-        checkQueryPermission(match, projectionIn, selection, sort);
+        checkPermissionCompat(match, projectionIn);
         switch (match) {
             case URL_TELEPHONY_USING_SUBID: {
                 subIdString = url.getLastPathSegment();
@@ -2847,7 +2935,9 @@
                     return null;
                 }
                 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
-                constraints.add(NUMERIC + " = '" + mTelephonyManager.getSimOperator(subId) + "'");
+                TelephonyManager telephonyManager = getContext()
+                    .getSystemService(TelephonyManager.class).createForSubscriptionId(subId);
+                constraints.add(NUMERIC + " = '" + telephonyManager.getSimOperator() + "'");
                 // TODO b/74213956 turn this back on once insertion includes correct sub id
                 // constraints.add(SUBSCRIPTION_ID + "=" + subIdString);
             }
@@ -3045,97 +3135,35 @@
         return ret;
     }
 
-    private void checkQueryPermission(int match, String[] projectionIn, String selection,
-            String sort) {
-        // Determine if we need to do a check for fields in the selection
-        boolean selectionOrSortContainsSensitiveFields;
-        try {
-            selectionOrSortContainsSensitiveFields = containsSensitiveFields(selection);
-            selectionOrSortContainsSensitiveFields |= containsSensitiveFields(sort);
-        } catch (IllegalArgumentException e) {
-            // Malformed sql, check permission anyway and return.
-            checkPermission();
-            return;
-        }
-
-        if (selectionOrSortContainsSensitiveFields) {
-            try {
-                checkPermission();
-            } catch (SecurityException e) {
-                EventLog.writeEvent(0x534e4554, "124107808", Binder.getCallingUid());
-                throw e;
-            }
-        }
-
-        if (match != URL_SIMINFO && match != URL_SIMINFO_USING_SUBID) {
-            if (projectionIn != null) {
-                for (String column : projectionIn) {
-                    if (TYPE.equals(column) ||
-                            MMSC.equals(column) ||
-                            MMSPROXY.equals(column) ||
-                            MMSPORT.equals(column) ||
-                            MVNO_TYPE.equals(column) ||
-                            MVNO_MATCH_DATA.equals(column) ||
-                            APN.equals(column)) {
-                    } else {
-                        checkPermission();
-                        break;
-                    }
-                }
-            } else {
-                // null returns all columns, so need permission check
-                checkPermission();
-            }
-        } else {
-            // if querying siminfo, caller should have read privilege permissions
-            checkPhonePrivilegePermission();
-        }
-    }
-
-    private boolean containsSensitiveFields(String sqlStatement) {
-        try {
-            SqlTokenFinder.findTokens(sqlStatement, s -> {
-                switch (s.toLowerCase()) {
-                    case USER:
-                    case PASSWORD:
-                    case SQL_SELECT_TOKEN:
-                        throw new SecurityException();
-                }
-            });
-        } catch (SecurityException e) {
-            return true;
-        }
-        return false;
-    }
-
     /**
-     * To find the current sim APN. Query APN based on {MCC, MNC, MVNO} to support backward
-     * compatibility but will move to carrier id in the future.
+     * To find the current sim APN. Query APN based on {MCC, MNC, MVNO} and {Carrier_ID}.
      *
      * There has three steps:
-     * 1. Query the APN based on { MCC, MNC, MVNO }.
-     * 2. If can't find the current APN, then query the parent APN. Query based on { MCC, MNC }.
-     * 3. else return empty cursor
-     *
+     * 1. Query the APN based on { MCC, MNC, MVNO } and if has results jump to step 3, else jump to
+     *    step 2.
+     * 2. Fallback to query the parent APN that query based on { MCC, MNC }.
+     * 3. Append the result with the APN that query based on { Carrier_ID }
      */
     private Cursor getSubscriptionMatchingAPNList(SQLiteQueryBuilder qb, String[] projectionIn,
             String selection, String[] selectionArgs, String sort, int subId) {
         Cursor ret;
-        final TelephonyManager tm = ((TelephonyManager)
-                getContext().getSystemService(Context.TELEPHONY_SERVICE))
+        final TelephonyManager tm = ((TelephonyManager) getContext()
+                .getSystemService(Context.TELEPHONY_SERVICE))
                 .createForSubscriptionId(subId);
         SQLiteDatabase db = getReadableDatabase();
         String mccmnc = tm.getSimOperator();
+        int carrierId = tm.getSimCarrierId();
 
         qb.appendWhereStandalone(IS_NOT_USER_DELETED + " and " +
                 IS_NOT_USER_DELETED_BUT_PRESENT_IN_XML + " and " +
                 IS_NOT_CARRIER_DELETED + " and " +
                 IS_NOT_CARRIER_DELETED_BUT_PRESENT_IN_XML);
 
-        // For query db one time, append step 1 and step 2 condition in one selection and
-        // separate results after the query is completed. Because IMSI has special match rule,
-        // so just query the MCC / MNC and filter the MVNO by ourselves
-        qb.appendWhereStandalone(NUMERIC + " = '" + mccmnc + "' ");
+        // For query db one time, append all conditions in one selection and separate results after
+        // the query is completed. IMSI has special match rule, so just query the MCC / MNC and
+        // filter the MVNO by ourselves
+        qb.appendWhereStandalone(NUMERIC + " = '" + mccmnc + "' OR " +
+                CARRIER_ID + " = '" + carrierId + "'");
 
         ret = qb.query(db, null, selection, selectionArgs, null, null, sort);
         if (ret == null) {
@@ -3145,51 +3173,86 @@
 
         if (DBG) log("match current APN size:  " + ret.getCount());
 
-        String[] coulmnNames = projectionIn != null ? projectionIn : ret.getColumnNames();
-        MatrixCursor currentCursor = new MatrixCursor(coulmnNames);
-        MatrixCursor parentCursor = new MatrixCursor(coulmnNames);
+        String[] columnNames = projectionIn != null ? projectionIn : ret.getColumnNames();
+        MatrixCursor currentCursor = new MatrixCursor(columnNames);
+        MatrixCursor parentCursor = new MatrixCursor(columnNames);
+        MatrixCursor carrierIdCursor = new MatrixCursor(columnNames);
 
         int numericIndex = ret.getColumnIndex(NUMERIC);
         int mvnoIndex = ret.getColumnIndex(MVNO_TYPE);
         int mvnoDataIndex = ret.getColumnIndex(MVNO_MATCH_DATA);
+        int carrierIdIndex = ret.getColumnIndex(CARRIER_ID);
 
-        IccRecords iccRecords = UiccController.getInstance().getIccRecords(
-                SubscriptionManager.getPhoneId(subId), UiccController.APP_FAM_3GPP);
-        if (iccRecords == null) {
-            loge("iccRecords is null");
-            return null;
-        }
-
-        //Separate the result into MatrixCursor
+        // Separate the result into MatrixCursor
         while (ret.moveToNext()) {
             List<String> data = new ArrayList<>();
-            for (String column : coulmnNames) {
+            for (String column : columnNames) {
                 data.add(ret.getString(ret.getColumnIndex(column)));
             }
 
-            if (!TextUtils.isEmpty(ret.getString(numericIndex)) &&
-                    ApnSettingUtils.mvnoMatches(iccRecords,
-                            ApnSetting.getMvnoTypeIntFromString(ret.getString(mvnoIndex)),
-                            ret.getString(mvnoDataIndex))) {
-                // 1. APN query result based on legacy SIM MCC/MCC and MVNO
+            boolean isMVNOAPN = !TextUtils.isEmpty(ret.getString(numericIndex))
+                    && tm.matchesCurrentSimOperator(ret.getString(numericIndex),
+                            getMvnoTypeIntFromString(ret.getString(mvnoIndex)),
+                            ret.getString(mvnoDataIndex));
+            boolean isMNOAPN = !TextUtils.isEmpty(ret.getString(numericIndex))
+                    && ret.getString(numericIndex).equals(mccmnc)
+                    && TextUtils.isEmpty(ret.getString(mvnoIndex));
+            boolean isCarrierIdAPN = !TextUtils.isEmpty(ret.getString(carrierIdIndex))
+                    && ret.getString(carrierIdIndex).equals(String.valueOf(carrierId))
+                    && carrierId != TelephonyManager.UNKNOWN_CARRIER_ID;
+
+            if (isMVNOAPN) {
+                // 1. The APN that query based on legacy SIM MCC/MCC and MVNO
                 currentCursor.addRow(data);
-            } else if (!TextUtils.isEmpty(ret.getString(numericIndex)) &&
-                    TextUtils.isEmpty(ret.getString(mvnoIndex))) {
-                // 2. APN query result based on SIM MCC/MNC
+            } else if (isMNOAPN) {
+                // 2. The APN that query based on SIM MCC/MNC
                 parentCursor.addRow(data);
+            } else if (isCarrierIdAPN) {
+                // The APN that query based on carrier Id (not include the MVNO or MNO APN)
+                carrierIdCursor.addRow(data);
             }
         }
         ret.close();
 
+        MatrixCursor result;
         if (currentCursor.getCount() > 0) {
             if (DBG) log("match MVNO APN: " + currentCursor.getCount());
-            return currentCursor;
+            result = currentCursor;
         } else if (parentCursor.getCount() > 0) {
             if (DBG) log("match MNO APN: " + parentCursor.getCount());
-            return parentCursor;
+            result = parentCursor;
         } else {
-            if (DBG) log("APN no match");
-            return new MatrixCursor(coulmnNames);
+            if (DBG) log("can't find the MVNO and MNO APN");
+            result = new MatrixCursor(columnNames);
+        }
+
+        if (DBG) log("match carrier id APN: " + carrierIdCursor.getCount());
+        appendCursorData(result, carrierIdCursor);
+        return result;
+    }
+
+    private static void appendCursorData(@NonNull MatrixCursor from, @NonNull MatrixCursor to) {
+        while (to.moveToNext()) {
+            List<Object> data = new ArrayList<>();
+            for (String column : to.getColumnNames()) {
+                int index = to.getColumnIndex(column);
+                switch (to.getType(index)) {
+                    case Cursor.FIELD_TYPE_INTEGER:
+                        data.add(to.getInt(index));
+                        break;
+                    case Cursor.FIELD_TYPE_FLOAT:
+                        data.add(to.getFloat(index));
+                        break;
+                    case Cursor.FIELD_TYPE_BLOB:
+                        data.add(to.getBlob(index));
+                        break;
+                    case Cursor.FIELD_TYPE_STRING:
+                    case Cursor.FIELD_TYPE_NULL:
+                        data.add(to.getString(index));
+                        break;
+                }
+            }
+            from.addRow(data);
         }
     }
 
@@ -3285,10 +3348,10 @@
             log("insert: exception " + e);
             // Insertion failed which could be due to a conflict. Check if that is the case
             // and merge the entries
-            Cursor oldRow = DatabaseHelper.selectConflictingRow(db, CARRIERS_TABLE, values);
+            Cursor oldRow = selectConflictingRow(db, CARRIERS_TABLE, values);
             if (oldRow != null) {
                 ContentValues mergedValues = new ContentValues();
-                DatabaseHelper.mergeFieldsAndUpdateDb(db, CARRIERS_TABLE, oldRow, values,
+                mergeFieldsAndUpdateDb(db, CARRIERS_TABLE, oldRow, values,
                         mergedValues, false, getContext());
                 oldRow.close();
                 notify = true;
@@ -3331,7 +3394,7 @@
                     values = new ContentValues();
                 }
 
-                values = DatabaseHelper.setDefaultValue(values);
+                values = setDefaultValue(values);
                 if (!values.containsKey(EDITED_STATUS)) {
                     values.put(EDITED_STATUS, CARRIER_EDITED);
                 }
@@ -3431,7 +3494,7 @@
 
             case URL_SIMINFO: {
                long id = db.insert(SIMINFO_TABLE, null, initialValues);
-               result = ContentUris.withAppendedId(SubscriptionManager.CONTENT_URI, id);
+               result = ContentUris.withAppendedId(Telephony.SimInfo.CONTENT_URI, id);
                break;
             }
         }
@@ -3462,7 +3525,7 @@
             case URL_DELETE:
             {
                 // Delete preferred APN for all subIds
-                deletePreferredApnId();
+                deletePreferredApnId(getContext());
                 // Delete unedited entries
                 count = db.delete(CARRIERS_TABLE, "(" + where + unedited + " and " +
                         IS_NOT_OWNED_BY_DPC, whereArgs);
@@ -3698,10 +3761,10 @@
                     // Update failed which could be due to a conflict. Check if that is
                     // the case and merge the entries
                     log("update: exception " + e);
-                    Cursor oldRow = DatabaseHelper.selectConflictingRow(db, CARRIERS_TABLE, values);
+                    Cursor oldRow = selectConflictingRow(db, CARRIERS_TABLE, values);
                     if (oldRow != null) {
                         ContentValues mergedValues = new ContentValues();
-                        DatabaseHelper.mergeFieldsAndUpdateDb(db, CARRIERS_TABLE, oldRow, values,
+                        mergeFieldsAndUpdateDb(db, CARRIERS_TABLE, oldRow, values,
                                 mergedValues, false, getContext());
                         oldRow.close();
                         db.delete(CARRIERS_TABLE, _ID + "=?" + " and " + IS_NOT_OWNED_BY_DPC,
@@ -3805,42 +3868,48 @@
                     // If not set, any change to SIMINFO will notify observers which listens to
                     // specific field of SIMINFO.
                     getContext().getContentResolver().notifyChange(
-                            SubscriptionManager.CONTENT_URI, null,
+                        Telephony.SimInfo.CONTENT_URI, null,
                             ContentResolver.NOTIFY_SYNC_TO_NETWORK
                                     | ContentResolver.NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS,
                             UserHandle.USER_ALL);
                     // notify observers on specific user settings changes.
-                    if (values.containsKey(SubscriptionManager.WFC_IMS_ENABLED)) {
+                    if (values.containsKey(Telephony.SimInfo.COLUMN_WFC_IMS_ENABLED)) {
                         getContext().getContentResolver().notifyChange(
                                 getNotifyContentUri(SubscriptionManager.WFC_ENABLED_CONTENT_URI,
                                         usingSubId, subId), null, true, UserHandle.USER_ALL);
                     }
-                    if (values.containsKey(SubscriptionManager.ENHANCED_4G_MODE_ENABLED)) {
+                    if (values.containsKey(Telephony.SimInfo.COLUMN_ENHANCED_4G_MODE_ENABLED)) {
                         getContext().getContentResolver().notifyChange(
                                 getNotifyContentUri(SubscriptionManager
                                                 .ADVANCED_CALLING_ENABLED_CONTENT_URI,
                                         usingSubId, subId), null, true, UserHandle.USER_ALL);
                     }
-                    if (values.containsKey(SubscriptionManager.VT_IMS_ENABLED)) {
+                    if (values.containsKey(Telephony.SimInfo.COLUMN_VT_IMS_ENABLED)) {
                         getContext().getContentResolver().notifyChange(
                                 getNotifyContentUri(SubscriptionManager.VT_ENABLED_CONTENT_URI,
                                         usingSubId, subId), null, true, UserHandle.USER_ALL);
                     }
-                    if (values.containsKey(SubscriptionManager.WFC_IMS_MODE)) {
+                    if (values.containsKey(Telephony.SimInfo.COLUMN_WFC_IMS_MODE)) {
                         getContext().getContentResolver().notifyChange(
                                 getNotifyContentUri(SubscriptionManager.WFC_MODE_CONTENT_URI,
                                         usingSubId, subId), null, true, UserHandle.USER_ALL);
                     }
-                    if (values.containsKey(SubscriptionManager.WFC_IMS_ROAMING_MODE)) {
+                    if (values.containsKey(Telephony.SimInfo.COLUMN_WFC_IMS_ROAMING_MODE)) {
                         getContext().getContentResolver().notifyChange(getNotifyContentUri(
                                 SubscriptionManager.WFC_ROAMING_MODE_CONTENT_URI,
                                 usingSubId, subId), null, true, UserHandle.USER_ALL);
                     }
-                    if (values.containsKey(SubscriptionManager.WFC_IMS_ROAMING_ENABLED)) {
+                    if (values.containsKey(Telephony.SimInfo.COLUMN_WFC_IMS_ROAMING_ENABLED)) {
                         getContext().getContentResolver().notifyChange(getNotifyContentUri(
                                 SubscriptionManager.WFC_ROAMING_ENABLED_CONTENT_URI,
                                 usingSubId, subId), null, true, UserHandle.USER_ALL);
                     }
+                    if (values.containsKey(Telephony.SimInfo.COLUMN_IMS_RCS_UCE_ENABLED)) {
+                        getContext().getContentResolver().notifyChange(getNotifyContentUri(
+                                Uri.withAppendedPath(Telephony.SimInfo.CONTENT_URI,
+                                        Telephony.SimInfo.COLUMN_IMS_RCS_UCE_ENABLED), usingSubId, subId),
+                                null, true, UserHandle.USER_ALL);
+                    }
                     break;
                 default:
                     getContext().getContentResolver().notifyChange(
@@ -3873,16 +3942,51 @@
                 return;
             }
         }
-        throw new SecurityException("No permission to write APN settings");
+
+
+        throw new SecurityException("No permission to access APN settings");
     }
 
-    private void checkPhonePrivilegePermission() {
-        int status = getContext().checkCallingOrSelfPermission(
-                "android.permission.READ_PRIVILEGED_PHONE_STATE");
-        if (status == PackageManager.PERMISSION_GRANTED) {
-            return;
+    /**
+     * Check permission to query the database based on PlatformCompat settings -- if the compat
+     * change is enabled, check WRITE_APN_SETTINGS or carrier privs for all queries. Otherwise,
+     * use the legacy checkQueryPermission method to see if the query should be allowed.
+     */
+    private void checkPermissionCompat(int match, String[] projectionIn) {
+        boolean useNewBehavior = CompatChanges.isChangeEnabled(
+                Telephony.Carriers.APN_READING_PERMISSION_CHANGE_ID,
+                Binder.getCallingUid());
+
+        if (!useNewBehavior) {
+            log("Using old permission behavior for telephony provider compat");
+            checkQueryPermission(match, projectionIn);
+        } else {
+            checkPermission();
         }
-        throw new SecurityException("No phone privilege permission");
+    }
+
+    private void checkQueryPermission(int match, String[] projectionIn) {
+        if (match != URL_SIMINFO) {
+            if (projectionIn != null) {
+                for (String column : projectionIn) {
+                    if (TYPE.equals(column) ||
+                            MMSC.equals(column) ||
+                            MMSPROXY.equals(column) ||
+                            MMSPORT.equals(column) ||
+                            MVNO_TYPE.equals(column) ||
+                            MVNO_MATCH_DATA.equals(column) ||
+                            APN.equals(column)) {
+                        // noop
+                    } else {
+                        checkPermission();
+                        break;
+                    }
+                }
+            } else {
+                // null returns all columns, so need permission check
+                checkPermission();
+            }
+        }
     }
 
     private DatabaseHelper mOpenHelper;
@@ -3928,13 +4032,9 @@
     }
 
     private String getWhereClauseForRestoreDefaultApn(SQLiteDatabase db, int subId) {
-        IccRecords iccRecords = getIccRecords(subId);
-        if (iccRecords == null) {
-            return null;
-        }
         TelephonyManager telephonyManager =
-                (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
-        String simOperator = telephonyManager.getSimOperator(subId);
+            getContext().getSystemService(TelephonyManager.class).createForSubscriptionId(subId);
+        String simOperator = telephonyManager.getSimOperator();
         Cursor cursor = db.query(CARRIERS_TABLE, new String[] {MVNO_TYPE, MVNO_MATCH_DATA},
                 NUMERIC + "='" + simOperator + "'", null, null, null, DEFAULT_SORT_ORDER);
         String where = null;
@@ -3945,8 +4045,8 @@
                 String mvnoType = cursor.getString(0 /* MVNO_TYPE index */);
                 String mvnoMatchData = cursor.getString(1 /* MVNO_MATCH_DATA index */);
                 if (!TextUtils.isEmpty(mvnoType) && !TextUtils.isEmpty(mvnoMatchData)
-                        && ApnSettingUtils.mvnoMatches(iccRecords,
-                        ApnSetting.getMvnoTypeIntFromString(mvnoType), mvnoMatchData)) {
+                        && telephonyManager.matchesCurrentSimOperator(simOperator,
+                            getMvnoTypeIntFromString(mvnoType), mvnoMatchData)) {
                     where = NUMERIC + "='" + simOperator + "'"
                             + " AND " + MVNO_TYPE + "='" + mvnoType + "'"
                             + " AND " + MVNO_MATCH_DATA + "='" + mvnoMatchData + "'"
@@ -3966,16 +4066,6 @@
         return where;
     }
 
-    @VisibleForTesting
-    IccRecords getIccRecords(int subId) {
-        TelephonyManager telephonyManager =
-                TelephonyManager.from(getContext()).createForSubscriptionId(subId);
-        int family = telephonyManager.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM ?
-                UiccController.APP_FAM_3GPP : UiccController.APP_FAM_3GPP2;
-        return UiccController.getInstance().getIccRecords(
-                SubscriptionManager.getPhoneId(subId), family);
-    }
-
     private synchronized void updateApnDb() {
         if (apnSourceServiceExists(getContext())) {
             loge("called updateApnDb when apn source service exists");
@@ -3990,7 +4080,7 @@
         SQLiteDatabase db = getWritableDatabase();
 
         // Delete preferred APN for all subIds
-        deletePreferredApnId();
+        deletePreferredApnId(getContext());
 
         // Delete entries in db
         try {
@@ -4012,10 +4102,10 @@
         int mcc, mnc;
         String subId;
         try {
-            mcc = c.getInt(c.getColumnIndexOrThrow(SubscriptionManager.MCC));
-            mnc = c.getInt(c.getColumnIndexOrThrow(SubscriptionManager.MNC));
+            mcc = c.getInt(c.getColumnIndexOrThrow(Telephony.SimInfo.COLUMN_MCC));
+            mnc = c.getInt(c.getColumnIndexOrThrow(Telephony.SimInfo.COLUMN_MNC));
             subId = c.getString(c.getColumnIndexOrThrow(
-                    SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID));
+                    Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID));
         } catch (IllegalArgumentException e) {
             Log.e(TAG, "Possible database corruption -- some columns not found.");
             return;
@@ -4024,10 +4114,10 @@
         String mccString = String.format(Locale.getDefault(), "%03d", mcc);
         String mncString = getBestStringMnc(context, mccString, mnc);
         ContentValues cv = new ContentValues(2);
-        cv.put(SubscriptionManager.MCC_STRING, mccString);
-        cv.put(SubscriptionManager.MNC_STRING, mncString);
+        cv.put(Telephony.SimInfo.COLUMN_MCC_STRING, mccString);
+        cv.put(Telephony.SimInfo.COLUMN_MNC_STRING, mncString);
         db.update(SIMINFO_TABLE, cv,
-                SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "=?",
+                Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID + "=?",
                 new String[]{subId});
     }
 
@@ -4064,17 +4154,17 @@
      */
     private static void syncBearerBitmaskAndNetworkTypeBitmask(ContentValues values) {
         if (values.containsKey(NETWORK_TYPE_BITMASK)) {
-            int convertedBitmask = ServiceState.convertNetworkTypeBitmaskToBearerBitmask(
+            int convertedBitmask = convertNetworkTypeBitmaskToBearerBitmask(
                     values.getAsInteger(NETWORK_TYPE_BITMASK));
             if (values.containsKey(BEARER_BITMASK)
                     && convertedBitmask != values.getAsInteger(BEARER_BITMASK)) {
                 loge("Network type bitmask and bearer bitmask are not compatible.");
             }
-            values.put(BEARER_BITMASK, ServiceState.convertNetworkTypeBitmaskToBearerBitmask(
+            values.put(BEARER_BITMASK, convertNetworkTypeBitmaskToBearerBitmask(
                     values.getAsInteger(NETWORK_TYPE_BITMASK)));
         } else {
             if (values.containsKey(BEARER_BITMASK)) {
-                int convertedBitmask = ServiceState.convertBearerBitmaskToNetworkTypeBitmask(
+                int convertedBitmask = convertBearerBitmaskToNetworkTypeBitmask(
                         values.getAsInteger(BEARER_BITMASK));
                 values.put(NETWORK_TYPE_BITMASK, convertedBitmask);
             }
@@ -4093,4 +4183,141 @@
     private static void loge(String s) {
         Log.e(TAG, s);
     }
+
+    private static int getMvnoTypeIntFromString(String mvnoType) {
+        String mvnoTypeString = TextUtils.isEmpty(mvnoType) ? mvnoType : mvnoType.toLowerCase();
+        Integer mvnoTypeInt = MVNO_TYPE_STRING_MAP.get(mvnoTypeString);
+        return  mvnoTypeInt == null ? UNSPECIFIED_INT : mvnoTypeInt;
+    }
+
+    private static int getBitmaskFromString(String bearerList) {
+        String[] bearers = bearerList.split("\\|");
+        int bearerBitmask = 0;
+        for (String bearer : bearers) {
+            int bearerInt = 0;
+            try {
+                bearerInt = Integer.parseInt(bearer.trim());
+            } catch (NumberFormatException nfe) {
+                return 0;
+            }
+
+            if (bearerInt == 0) {
+                return 0;
+            }
+            bearerBitmask |= getBitmaskForTech(bearerInt);
+        }
+        return bearerBitmask;
+    }
+
+    /**
+     * Transform RIL radio technology value to Network
+     * type bitmask{@link android.telephony.TelephonyManager.NetworkTypeBitMask}.
+     *
+     * @param rat The RIL radio technology.
+     * @return The network type
+     * bitmask{@link android.telephony.TelephonyManager.NetworkTypeBitMask}.
+     */
+    private static int rilRadioTechnologyToNetworkTypeBitmask(int rat) {
+        switch (rat) {
+            case RIL_RADIO_TECHNOLOGY_GPRS:
+                return (int) TelephonyManager.NETWORK_TYPE_BITMASK_GPRS;
+            case RIL_RADIO_TECHNOLOGY_EDGE:
+                return (int) TelephonyManager.NETWORK_TYPE_BITMASK_EDGE;
+            case RIL_RADIO_TECHNOLOGY_UMTS:
+                return (int) TelephonyManager.NETWORK_TYPE_BITMASK_UMTS;
+            case RIL_RADIO_TECHNOLOGY_HSDPA:
+                return (int) TelephonyManager.NETWORK_TYPE_BITMASK_HSDPA;
+            case RIL_RADIO_TECHNOLOGY_HSUPA:
+                return (int) TelephonyManager.NETWORK_TYPE_BITMASK_HSUPA;
+            case RIL_RADIO_TECHNOLOGY_HSPA:
+                return (int) TelephonyManager.NETWORK_TYPE_BITMASK_HSPA;
+            case RIL_RADIO_TECHNOLOGY_IS95A:
+            case RIL_RADIO_TECHNOLOGY_IS95B:
+                return (int) TelephonyManager.NETWORK_TYPE_BITMASK_CDMA;
+            case RIL_RADIO_TECHNOLOGY_1xRTT:
+                return (int) TelephonyManager.NETWORK_TYPE_BITMASK_1xRTT;
+            case RIL_RADIO_TECHNOLOGY_EVDO_0:
+                return (int) TelephonyManager.NETWORK_TYPE_BITMASK_EVDO_0;
+            case RIL_RADIO_TECHNOLOGY_EVDO_A:
+                return (int) TelephonyManager.NETWORK_TYPE_BITMASK_EVDO_A;
+            case RIL_RADIO_TECHNOLOGY_EVDO_B:
+                return (int) TelephonyManager.NETWORK_TYPE_BITMASK_EVDO_B;
+            case RIL_RADIO_TECHNOLOGY_EHRPD:
+                return (int) TelephonyManager.NETWORK_TYPE_BITMASK_EHRPD;
+            case RIL_RADIO_TECHNOLOGY_LTE:
+                return (int) TelephonyManager.NETWORK_TYPE_BITMASK_LTE;
+            case RIL_RADIO_TECHNOLOGY_HSPAP:
+                return (int) TelephonyManager.NETWORK_TYPE_BITMASK_HSPAP;
+            case RIL_RADIO_TECHNOLOGY_GSM:
+                return (int) TelephonyManager.NETWORK_TYPE_BITMASK_GSM;
+            case RIL_RADIO_TECHNOLOGY_TD_SCDMA:
+                return (int) TelephonyManager.NETWORK_TYPE_BITMASK_TD_SCDMA;
+            case RIL_RADIO_TECHNOLOGY_IWLAN:
+                return (int) TelephonyManager.NETWORK_TYPE_BITMASK_IWLAN;
+            case RIL_RADIO_TECHNOLOGY_LTE_CA:
+                return (int) TelephonyManager.NETWORK_TYPE_BITMASK_LTE_CA;
+            case RIL_RADIO_TECHNOLOGY_NR:
+                return (int) TelephonyManager.NETWORK_TYPE_BITMASK_NR;
+            default:
+                return (int) TelephonyManager.NETWORK_TYPE_BITMASK_UNKNOWN;
+        }
+    }
+
+    /**
+     * Convert network type bitmask to bearer bitmask.
+     *
+     * @param networkTypeBitmask The network type bitmask value
+     * @return The bearer bitmask value.
+     */
+    private static int convertNetworkTypeBitmaskToBearerBitmask(int networkTypeBitmask) {
+        if (networkTypeBitmask == 0) {
+            return 0;
+        }
+
+        int bearerBitmask = 0;
+        for (int bearerInt = 0; bearerInt < NEXT_RIL_RADIO_TECHNOLOGY; bearerInt++) {
+            if (bitmaskHasTarget(networkTypeBitmask,
+                    rilRadioTechnologyToNetworkTypeBitmask(bearerInt))) {
+                bearerBitmask |= getBitmaskForTech(bearerInt);
+            }
+        }
+        return bearerBitmask;
+    }
+
+    /**
+     * Convert bearer bitmask to network type bitmask.
+     *
+     * @param bearerBitmask The bearer bitmask value.
+     * @return The network type bitmask value.
+     */
+    private static int convertBearerBitmaskToNetworkTypeBitmask(int bearerBitmask) {
+        if (bearerBitmask == 0) {
+            return 0;
+        }
+
+        int networkTypeBitmask = 0;
+        for (int bearerUnitInt = 0; bearerUnitInt < NEXT_RIL_RADIO_TECHNOLOGY; bearerUnitInt++) {
+            int bearerUnitBitmask = getBitmaskForTech(bearerUnitInt);
+            if (bitmaskHasTarget(bearerBitmask, bearerUnitBitmask)) {
+                networkTypeBitmask |= rilRadioTechnologyToNetworkTypeBitmask(bearerUnitInt);
+            }
+        }
+        return networkTypeBitmask;
+    }
+
+    private static boolean bitmaskHasTarget(int bearerBitmask, int targetBitmask) {
+        if (bearerBitmask == 0) {
+            return true;
+        } else if (targetBitmask != 0) {
+            return ((bearerBitmask & targetBitmask) != 0);
+        }
+        return false;
+    }
+
+    private static int getBitmaskForTech(int radioTech) {
+        if (radioTech >= 1) {
+            return (1 << (radioTech - 1));
+        }
+        return 0;
+    }
 }
diff --git a/tests/AndroidTest.xml b/tests/AndroidTest.xml
index 23310f9..bb0261e 100644
--- a/tests/AndroidTest.xml
+++ b/tests/AndroidTest.xml
@@ -20,7 +20,7 @@
 
     <option name="test-suite-tag" value="apct" />
     <option name="test-tag" value="TelephonyProviderTests" />
-    <test class="com.android.tradefed.testtype.InstrumentationTest" >
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.android.providers.telephony.tests" />
         <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
         <option name="hidden-api-checks" value="false"/>
diff --git a/tests/src/com/android/providers/telephony/CarrierIdProviderTest.java b/tests/src/com/android/providers/telephony/CarrierIdProviderTest.java
index bc39260..ee0e016 100644
--- a/tests/src/com/android/providers/telephony/CarrierIdProviderTest.java
+++ b/tests/src/com/android/providers/telephony/CarrierIdProviderTest.java
@@ -17,6 +17,7 @@
 package com.android.providers.telephony;
 
 import android.content.ContentValues;
+import android.content.Context;
 import android.content.SharedPreferences;
 import android.content.pm.PackageManager;
 import android.content.pm.ProviderInfo;
@@ -26,23 +27,21 @@
 import android.net.Uri;
 import android.os.Handler;
 import android.provider.Telephony.CarrierId;
+import android.telephony.SubscriptionManager;
 import android.test.mock.MockContentResolver;
 import android.test.mock.MockContext;
 import android.util.Log;
 
-import com.android.internal.telephony.SubscriptionController;
-
 import junit.framework.TestCase;
 
 import org.junit.Assert;
 import org.junit.Test;
 
-import java.lang.reflect.Field;
-
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 /**
  * Tests for testing CRUD operations of CarrierIdProvider.
@@ -77,12 +76,12 @@
     private CarrierIdProviderTestable mCarrierIdProviderTestable;
     private FakeContentObserver mContentObserver;
     private SharedPreferences mSharedPreferences = mock(SharedPreferences.class);
-    private SubscriptionController mSubController = mock(SubscriptionController.class);
+    private SubscriptionManager subscriptionManager = mock(SubscriptionManager.class);
 
     private class FakeContentResolver extends MockContentResolver {
         @Override
-        public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
-            super.notifyChange(uri, observer, syncToNetwork);
+        public void notifyChange(Uri uri, ContentObserver observer) {
+            super.notifyChange(uri, observer);
             Log.d(TAG, "onChanged(uri=" + uri + ")" + observer);
             mContentObserver.dispatchChange(false, uri);
         }
@@ -121,8 +120,13 @@
 
         @Override
         public Object getSystemService(String name) {
-            Log.d(TAG, "getSystemService: returning null");
-            return null;
+            switch (name) {
+                case Context.TELEPHONY_SUBSCRIPTION_SERVICE:
+                    return subscriptionManager;
+                default:
+                    Log.d(TAG, "getSystemService: returning null");
+                    return null;
+            }
         }
 
         @Override
@@ -148,12 +152,6 @@
         mContext = new MockContextWithProvider(mCarrierIdProviderTestable);
         mContentResolver = mContext.getContentResolver();
         mContentObserver = new FakeContentObserver(null);
-
-        doReturn("").when(mSubController).getDataEnabledOverrideRules(anyInt());
-
-        Field field = SubscriptionController.class.getDeclaredField("sInstance");
-        field.setAccessible(true);
-        field.set(null, mSubController);
     }
 
     @Override
@@ -341,8 +339,7 @@
             ContentValues cv = new ContentValues();
             cv.put(CarrierId.CARRIER_ID, dummy_cid);
             cv.put(CarrierId.CARRIER_NAME, dummy_name);
-            doReturn(1).when(mSubController).getDefaultSubId();
-            doReturn(true).when(mSubController).isActiveSubId(eq(1));
+            when(subscriptionManager.isActiveSubscriptionId(eq(1))).thenReturn(true);
             mContext.getContentResolver().update(Uri.withAppendedPath(CarrierId.CONTENT_URI,
                     "1"), cv, null, null);
         } catch (Exception e) {
@@ -351,7 +348,6 @@
         }
         int carrierId = -1;
         String carrierName = null;
-
         // query carrier id for subId 1
         try {
             final Cursor c = mContext.getContentResolver().query(
@@ -416,9 +412,6 @@
             ContentValues cv = new ContentValues();
             cv.put(CarrierId.CARRIER_ID, dummy_cid);
             cv.put(CarrierId.CARRIER_NAME, dummy_name);
-            doReturn(1).when(mSubController).getDefaultSubId();
-            doReturn(true).when(mSubController).isActiveSubId(eq(1));
-
             mContext.getContentResolver().update(CarrierId.CONTENT_URI, cv, null, null);
             Assert.fail("should throw an exception for wrong uri");
         } catch (IllegalArgumentException ex) {
diff --git a/tests/src/com/android/providers/telephony/CellBroadcastProviderTest.java b/tests/src/com/android/providers/telephony/CellBroadcastProviderTest.java
deleted file mode 100644
index b5ff07b..0000000
--- a/tests/src/com/android/providers/telephony/CellBroadcastProviderTest.java
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * Copyright (C) 2019 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 static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.doReturn;
-
-import junit.framework.TestCase;
-
-import android.content.ContentValues;
-import android.content.pm.PackageManager;
-import android.database.Cursor;
-import android.net.Uri;
-import android.provider.Telephony.CellBroadcasts;
-import android.test.mock.MockContentResolver;
-import android.test.mock.MockContext;
-import android.util.Log;
-
-import com.android.providers.telephony.CellBroadcastProvider.PermissionChecker;
-
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-public class CellBroadcastProviderTest extends TestCase {
-    private static final String TAG = CellBroadcastProviderTest.class.getSimpleName();
-
-    public static final Uri CONTENT_URI = Uri.parse("content://cellbroadcasts_fwk");
-
-    private static final int GEO_SCOPE = 1;
-    private static final String PLMN = "123456";
-    private static final int LAC = 13;
-    private static final int CID = 123;
-    private static final int SERIAL_NUMBER = 17984;
-    private static final int SERVICE_CATEGORY = 4379;
-    private static final String LANGUAGE_CODE = "en";
-    private static final String MESSAGE_BODY = "AMBER Alert: xxxx";
-    private static final int MESSAGE_FORMAT = 1;
-    private static final int MESSAGE_PRIORITY = 3;
-    private static final int ETWS_WARNING_TYPE = 1;
-    private static final int CMAS_MESSAGE_CLASS = 1;
-    private static final int CMAS_CATEGORY = 6;
-    private static final int CMAS_RESPONSE_TYPE = 1;
-    private static final int CMAS_SEVERITY = 2;
-    private static final int CMAS_URGENCY = 3;
-    private static final int CMAS_CERTAINTY = 4;
-    private static final int RECEIVED_TIME = 1562792637;
-    private static final int MESSAGE_BROADCASTED = 1;
-    private static final String GEOMETRIES_COORDINATES
-            = "polygon|0,0|0,1|1,1|1,0;circle|0,0|100";
-
-    private static final String SELECT_BY_ID = CellBroadcasts._ID + "=?";
-
-    private static final String[] QUERY_COLUMNS = {
-            CellBroadcasts._ID,
-            CellBroadcasts.GEOGRAPHICAL_SCOPE,
-            CellBroadcasts.PLMN,
-            CellBroadcasts.LAC,
-            CellBroadcasts.CID,
-            CellBroadcasts.SERIAL_NUMBER,
-            CellBroadcasts.SERVICE_CATEGORY,
-            CellBroadcasts.LANGUAGE_CODE,
-            CellBroadcasts.MESSAGE_BODY,
-            CellBroadcasts.MESSAGE_FORMAT,
-            CellBroadcasts.MESSAGE_PRIORITY,
-            CellBroadcasts.ETWS_WARNING_TYPE,
-            CellBroadcasts.CMAS_MESSAGE_CLASS,
-            CellBroadcasts.CMAS_CATEGORY,
-            CellBroadcasts.CMAS_RESPONSE_TYPE,
-            CellBroadcasts.CMAS_SEVERITY,
-            CellBroadcasts.CMAS_URGENCY,
-            CellBroadcasts.CMAS_CERTAINTY,
-            CellBroadcasts.RECEIVED_TIME,
-            CellBroadcasts.MESSAGE_BROADCASTED,
-            CellBroadcasts.GEOMETRIES
-    };
-
-    private CellBroadcastProviderTestable mCellBroadcastProviderTestable;
-    private MockContextWithProvider mContext;
-    private MockContentResolver mContentResolver;
-
-    @Mock
-    private PermissionChecker mMockPermissionChecker;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        MockitoAnnotations.initMocks(this);
-        doReturn(true).when(mMockPermissionChecker).hasReadPermission();
-        doReturn(true).when(mMockPermissionChecker).hasWritePermission();
-
-        mCellBroadcastProviderTestable = new CellBroadcastProviderTestable(mMockPermissionChecker);
-        mContext = new MockContextWithProvider(mCellBroadcastProviderTestable);
-        mContentResolver = mContext.getContentResolver();
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        mCellBroadcastProviderTestable.closeDatabase();
-        super.tearDown();
-    }
-
-    @Test
-    public void testUpdate() {
-        // Insert a cellbroadcast to the database.
-        ContentValues cv = fakeCellBroadcast();
-        Uri uri = mContentResolver.insert(CONTENT_URI, cv);
-        assertThat(uri).isNotNull();
-
-        // Change some fields of this cell broadcast.
-        int messageBroadcasted = 1 - cv.getAsInteger(CellBroadcasts.MESSAGE_BROADCASTED);
-        int receivedTime = 1234555555;
-        cv.put(CellBroadcasts.MESSAGE_BROADCASTED, messageBroadcasted);
-        cv.put(CellBroadcasts.RECEIVED_TIME, receivedTime);
-        mContentResolver.update(CONTENT_URI, cv, SELECT_BY_ID,
-                new String[] { uri.getLastPathSegment() });
-
-        // Query and check if the update is successed.
-        Cursor cursor = mContentResolver.query(CONTENT_URI, QUERY_COLUMNS,
-                SELECT_BY_ID, new String[] { uri.getLastPathSegment() }, null /* orderBy */);
-        cursor.moveToNext();
-
-        assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.RECEIVED_TIME)))
-                .isEqualTo(receivedTime);
-        assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.MESSAGE_BROADCASTED)))
-                .isEqualTo(messageBroadcasted);
-        cursor.close();
-    }
-
-    @Test
-    public void testUpdate_WithoutWritePermission_fail() {
-        ContentValues cv = fakeCellBroadcast();
-        Uri uri = mContentResolver.insert(CONTENT_URI, cv);
-        assertThat(uri).isNotNull();
-
-        // Revoke the write permission
-        doReturn(false).when(mMockPermissionChecker).hasWritePermission();
-
-        try {
-            mContentResolver.update(CONTENT_URI, cv, SELECT_BY_ID,
-                    new String[] { uri.getLastPathSegment() });
-            fail();
-        } catch (SecurityException ex) {
-            // pass the test
-        }
-    }
-
-    @Test
-    public void testGetAllCellBroadcast() {
-        // Insert some cell broadcasts which message_broadcasted is false
-        int messageNotBroadcastedCount = 5;
-        ContentValues cv = fakeCellBroadcast();
-        cv.put(CellBroadcasts.MESSAGE_BROADCASTED, 0);
-        for (int i = 0; i < messageNotBroadcastedCount; i++) {
-            mContentResolver.insert(CONTENT_URI, cv);
-        }
-
-        // Insert some cell broadcasts which message_broadcasted is true
-        int messageBroadcastedCount = 6;
-        cv.put(CellBroadcasts.MESSAGE_BROADCASTED, 1);
-        for (int i = 0; i < messageBroadcastedCount; i++) {
-            mContentResolver.insert(CONTENT_URI, cv);
-        }
-
-        // Query the broadcast with message_broadcasted is false
-        Cursor cursor = mContentResolver.query(
-                CONTENT_URI,
-                QUERY_COLUMNS,
-                String.format("%s=?", CellBroadcasts.MESSAGE_BROADCASTED), /* selection */
-                new String[] {"0"}, /* selectionArgs */
-                null /* sortOrder */);
-        assertThat(cursor.getCount()).isEqualTo(messageNotBroadcastedCount);
-    }
-
-    @Test
-    public void testDelete_withoutWritePermission_throwSecurityException() {
-        Uri uri = mContentResolver.insert(CONTENT_URI, fakeCellBroadcast());
-        assertThat(uri).isNotNull();
-
-        // Revoke the write permission
-        doReturn(false).when(mMockPermissionChecker).hasWritePermission();
-
-        try {
-            mContentResolver.delete(CONTENT_URI, SELECT_BY_ID,
-                    new String[] { uri.getLastPathSegment() });
-            fail();
-        } catch (SecurityException ex) {
-            // pass the test
-        }
-    }
-
-
-    @Test
-    public void testDelete_oneRecord_success() {
-        // Insert a cellbroadcast to the database.
-        ContentValues cv = fakeCellBroadcast();
-        Uri uri = mContentResolver.insert(CONTENT_URI, cv);
-        assertThat(uri).isNotNull();
-
-        String[] selectionArgs = new String[] { uri.getLastPathSegment() };
-
-        // Ensure the cell broadcast is inserted.
-        Cursor cursor = mContentResolver.query(CONTENT_URI, QUERY_COLUMNS,
-                SELECT_BY_ID, selectionArgs, null /* orderBy */);
-        assertThat(cursor.getCount()).isEqualTo(1);
-        cursor.close();
-
-        // Delete the cell broadcast
-        int rowCount = mContentResolver.delete(CONTENT_URI, SELECT_BY_ID,
-                selectionArgs);
-        assertThat(rowCount).isEqualTo(1);
-
-        // Ensure the cell broadcast is deleted.
-        cursor = mContentResolver.query(CONTENT_URI, QUERY_COLUMNS, SELECT_BY_ID,
-                selectionArgs, null /* orderBy */);
-        assertThat(cursor.getCount()).isEqualTo(0);
-        cursor.close();
-    }
-
-    @Test
-    public void testDelete_all_success() {
-        // Insert a cellbroadcast to the database.
-        mContentResolver.insert(CONTENT_URI, fakeCellBroadcast());
-        mContentResolver.insert(CONTENT_URI, fakeCellBroadcast());
-
-        // Ensure the cell broadcast are inserted.
-        Cursor cursor = mContentResolver.query(CONTENT_URI, QUERY_COLUMNS,
-                null /* selection */, null /* selectionArgs */, null /* orderBy */);
-        assertThat(cursor.getCount()).isEqualTo(2);
-        cursor.close();
-
-        // Delete all cell broadcasts.
-        int rowCount = mContentResolver.delete(
-                CONTENT_URI, null /* selection */, null /* selectionArgs */);
-        assertThat(rowCount).isEqualTo(2);
-        cursor.close();
-
-        // Ensure all cell broadcasts are deleted.
-        cursor = mContentResolver.query(CONTENT_URI, QUERY_COLUMNS,
-                null /* selection */, null /* selectionArgs */, null /* orderBy */);
-        assertThat(cursor.getCount()).isEqualTo(0);
-        cursor.close();
-    }
-
-    @Test
-    public void testInsert_withoutWritePermission_fail() {
-        doReturn(false).when(mMockPermissionChecker).hasWritePermission();
-
-        try {
-            mContentResolver.insert(CONTENT_URI, fakeCellBroadcast());
-            fail();
-        } catch (SecurityException ex) {
-            // pass the test
-        }
-    }
-
-    @Test
-    public void testInsertAndQuery() {
-        // Insert a cell broadcast message
-        Uri uri = mContentResolver.insert(CONTENT_URI, fakeCellBroadcast());
-
-        // Verify that the return uri is not null and the record is inserted into the database
-        // correctly.
-        assertThat(uri).isNotNull();
-        Cursor cursor = mContentResolver.query(
-                CONTENT_URI, QUERY_COLUMNS, SELECT_BY_ID,
-                new String[] { uri.getLastPathSegment() }, null /* orderBy */);
-        assertThat(cursor.getCount()).isEqualTo(1);
-
-        cursor.moveToNext();
-        assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.GEOGRAPHICAL_SCOPE)))
-                .isEqualTo(GEO_SCOPE);
-        assertThat(cursor.getString(cursor.getColumnIndexOrThrow(CellBroadcasts.PLMN)))
-                .isEqualTo(PLMN);
-        assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.LAC))).isEqualTo(LAC);
-        assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CID))).isEqualTo(CID);
-        assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.SERIAL_NUMBER)))
-                .isEqualTo(SERIAL_NUMBER);
-        assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.SERVICE_CATEGORY)))
-                .isEqualTo(SERVICE_CATEGORY);
-        assertThat(cursor.getString(cursor.getColumnIndexOrThrow(CellBroadcasts.LANGUAGE_CODE)))
-                .isEqualTo(LANGUAGE_CODE);
-        assertThat(cursor.getString(cursor.getColumnIndexOrThrow(CellBroadcasts.MESSAGE_BODY)))
-                .isEqualTo(MESSAGE_BODY);
-        assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.MESSAGE_FORMAT)))
-                .isEqualTo(MESSAGE_FORMAT);
-        assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.MESSAGE_PRIORITY)))
-                .isEqualTo(MESSAGE_PRIORITY);
-        assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.ETWS_WARNING_TYPE)))
-                .isEqualTo(ETWS_WARNING_TYPE);
-        assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CMAS_MESSAGE_CLASS)))
-                .isEqualTo(CMAS_MESSAGE_CLASS);
-        assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CMAS_CATEGORY)))
-                .isEqualTo(CMAS_CATEGORY);
-        assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CMAS_RESPONSE_TYPE)))
-                .isEqualTo(CMAS_RESPONSE_TYPE);
-        assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CMAS_SEVERITY)))
-                .isEqualTo(CMAS_SEVERITY);
-        assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CMAS_URGENCY)))
-                .isEqualTo(CMAS_URGENCY);
-        assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CMAS_CERTAINTY)))
-                .isEqualTo(CMAS_CERTAINTY);
-        assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.RECEIVED_TIME)))
-                .isEqualTo(RECEIVED_TIME);
-        assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.MESSAGE_BROADCASTED)))
-                .isEqualTo(MESSAGE_BROADCASTED);
-        assertThat(cursor.getString(cursor.getColumnIndexOrThrow(
-                CellBroadcasts.GEOMETRIES))).isEqualTo(GEOMETRIES_COORDINATES);
-    }
-
-    /**
-     * This is used to give the CellBroadcastProviderTest a mocked context which takes a
-     * CellBroadcastProvider and attaches it to the ContentResolver.
-     */
-    private class MockContextWithProvider extends MockContext {
-        private final MockContentResolver mResolver;
-
-        public MockContextWithProvider(CellBroadcastProviderTestable cellBroadcastProvider) {
-            mResolver = new MockContentResolver();
-            cellBroadcastProvider.initializeForTesting(this);
-
-            // Add given cellBroadcastProvider to mResolver, so that mResolver can send queries
-            // to the provider.
-            mResolver.addProvider(CellBroadcastProvider.AUTHORITY, cellBroadcastProvider);
-        }
-
-        @Override
-        public MockContentResolver getContentResolver() {
-            return mResolver;
-        }
-
-
-        @Override
-        public Object getSystemService(String name) {
-            Log.d(TAG, "getSystemService: returning null");
-            return null;
-        }
-
-        @Override
-        public int checkCallingOrSelfPermission(String permission) {
-            return PackageManager.PERMISSION_GRANTED;
-        }
-    }
-
-    private static ContentValues fakeCellBroadcast() {
-        ContentValues cv = new ContentValues();
-        cv.put(CellBroadcasts.GEOGRAPHICAL_SCOPE, GEO_SCOPE);
-        cv.put(CellBroadcasts.PLMN, PLMN);
-        cv.put(CellBroadcasts.LAC, LAC);
-        cv.put(CellBroadcasts.CID, CID);
-        cv.put(CellBroadcasts.SERIAL_NUMBER, SERIAL_NUMBER);
-        cv.put(CellBroadcasts.SERVICE_CATEGORY, SERVICE_CATEGORY);
-        cv.put(CellBroadcasts.LANGUAGE_CODE, LANGUAGE_CODE);
-        cv.put(CellBroadcasts.MESSAGE_BODY, MESSAGE_BODY);
-        cv.put(CellBroadcasts.MESSAGE_FORMAT, MESSAGE_FORMAT);
-        cv.put(CellBroadcasts.MESSAGE_PRIORITY, MESSAGE_PRIORITY);
-        cv.put(CellBroadcasts.ETWS_WARNING_TYPE, ETWS_WARNING_TYPE);
-        cv.put(CellBroadcasts.CMAS_MESSAGE_CLASS, CMAS_MESSAGE_CLASS);
-        cv.put(CellBroadcasts.CMAS_CATEGORY, CMAS_CATEGORY);
-        cv.put(CellBroadcasts.CMAS_RESPONSE_TYPE, CMAS_RESPONSE_TYPE);
-        cv.put(CellBroadcasts.CMAS_SEVERITY, CMAS_SEVERITY);
-        cv.put(CellBroadcasts.CMAS_URGENCY, CMAS_URGENCY);
-        cv.put(CellBroadcasts.CMAS_CERTAINTY, CMAS_CERTAINTY);
-        cv.put(CellBroadcasts.RECEIVED_TIME, RECEIVED_TIME);
-        cv.put(CellBroadcasts.MESSAGE_BROADCASTED, MESSAGE_BROADCASTED);
-        cv.put(CellBroadcasts.GEOMETRIES, GEOMETRIES_COORDINATES);
-        return cv;
-    }
-}
diff --git a/tests/src/com/android/providers/telephony/CellBroadcastProviderTestable.java b/tests/src/com/android/providers/telephony/CellBroadcastProviderTestable.java
deleted file mode 100644
index 8334312..0000000
--- a/tests/src/com/android/providers/telephony/CellBroadcastProviderTestable.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2019 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.content.Context;
-import android.content.pm.ProviderInfo;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.util.Log;
-
-import androidx.test.InstrumentationRegistry;
-
-public class CellBroadcastProviderTestable extends CellBroadcastProvider {
-    private static final String TAG = CellBroadcastProviderTestable.class.getSimpleName();
-
-    public CellBroadcastProviderTestable(PermissionChecker permissionChecker) {
-        super(permissionChecker);
-    }
-
-    @Override
-    public boolean onCreate() {
-        // DO NOT call super.onCreate(), otherwise the permission checker will be override.
-        Log.d(TAG, "CellBroadcastProviderTestable onCreate");
-        mDbHelper = new InMemoryCellBroadcastProviderDbHelper();
-        return true;
-    }
-
-    public void closeDatabase() {
-        mDbHelper.close();
-    }
-
-    public static class InMemoryCellBroadcastProviderDbHelper extends SQLiteOpenHelper {
-        public InMemoryCellBroadcastProviderDbHelper() {
-            super(InstrumentationRegistry.getTargetContext(),
-                    null,    // db file name is null for in-memory db
-                    null,    // CursorFactory is null by default
-                    1);      // db version is no-op for tests
-        }
-
-        @Override
-        public void onCreate(SQLiteDatabase db) {
-            Log.d(TAG, "IN MEMORY DB CREATED");
-            db.execSQL(getStringForCellBroadcastTableCreation(CELL_BROADCASTS_TABLE_NAME));
-        }
-
-        @Override
-        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}
-    }
-
-    public void initializeForTesting(Context context) {
-        ProviderInfo providerInfo = new ProviderInfo();
-        providerInfo.authority = CellBroadcastProvider.AUTHORITY;
-
-        // Add context to given carrierIdProvider
-        attachInfoForTesting(context, providerInfo);
-    }
-}
diff --git a/tests/src/com/android/providers/telephony/RcsProviderDeleteTest.java b/tests/src/com/android/providers/telephony/RcsProviderDeleteTest.java
deleted file mode 100644
index c0cef0a..0000000
--- a/tests/src/com/android/providers/telephony/RcsProviderDeleteTest.java
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * 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 static android.provider.Telephony.RcsColumns.RcsGroupThreadColumns.GROUP_NAME_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsGroupThreadColumns.OWNER_PARTICIPANT_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.CANONICAL_ADDRESS_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.RCS_ALIAS_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantEventColumns.NEW_ALIAS_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.NEW_NAME_COLUMN;
-
-import static com.android.providers.telephony.RcsProvider.RCS_MESSAGE_TABLE;
-import static com.android.providers.telephony.RcsProviderHelper.setup1To1Thread;
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.net.Uri;
-import android.test.mock.MockContentResolver;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
-
-@RunWith(AndroidJUnit4.class)
-public class RcsProviderDeleteTest {
-    private MockContentResolver mContentResolver;
-    private RcsProviderTestable mRcsProvider;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mRcsProvider = new RcsProviderTestable();
-        RcsProviderTestable.MockContextWithProvider
-                context = new RcsProviderTestable.MockContextWithProvider(mRcsProvider);
-        mContentResolver = context.getContentResolver();
-
-        // insert a participant
-        //  first into the MmsSmsProvider
-        mRcsProvider.getWritableDatabase().execSQL(
-                "INSERT INTO canonical_addresses VALUES (1, \"+15551234567\")");
-
-        //  then into the RcsProvider
-        ContentValues participantValues = new ContentValues();
-        participantValues.put(RCS_ALIAS_COLUMN, "Bob");
-        participantValues.put(CANONICAL_ADDRESS_ID_COLUMN, 1);
-        assertThat(mContentResolver.insert(Uri.parse("content://rcs/participant"),
-                participantValues)).isEqualTo(Uri.parse("content://rcs/participant/1"));
-
-        setup1To1Thread(mContentResolver);
-
-        // insert one group thread
-        ContentValues groupContentValues = new ContentValues();
-        groupContentValues.put(OWNER_PARTICIPANT_COLUMN, 1);
-        groupContentValues.put(GROUP_NAME_COLUMN, "name");
-        Uri groupThreadUri = Uri.parse("content://rcs/group_thread");
-        assertThat(mContentResolver.insert(groupThreadUri, groupContentValues)).isEqualTo(
-                Uri.parse("content://rcs/group_thread/2"));
-
-        Uri addParticipantToGroupThread = Uri.parse("content://rcs/group_thread/2/participant/1");
-        assertThat(mContentResolver.insert(addParticipantToGroupThread, null)).isEqualTo(
-                addParticipantToGroupThread);
-
-        // add incoming and outgoing messages to both threads
-        ContentValues messageValues = new ContentValues();
-        assertThat(mContentResolver.insert(Uri.parse("content://rcs/p2p_thread/1/incoming_message"),
-                messageValues)).isEqualTo(
-                Uri.parse("content://rcs/p2p_thread/1/incoming_message/1"));
-        assertThat(mContentResolver.insert(Uri.parse("content://rcs/p2p_thread/1/outgoing_message"),
-                messageValues)).isEqualTo(
-                Uri.parse("content://rcs/p2p_thread/1/outgoing_message/2"));
-        assertThat(
-                mContentResolver.insert(Uri.parse("content://rcs/group_thread/2/incoming_message"),
-                        messageValues)).isEqualTo(
-                Uri.parse("content://rcs/group_thread/2/incoming_message/3"));
-        assertThat(
-                mContentResolver.insert(Uri.parse("content://rcs/group_thread/2/outgoing_message"),
-                        messageValues)).isEqualTo(
-                Uri.parse("content://rcs/group_thread/2/outgoing_message/4"));
-
-        // add a file transfer to a message
-        ContentValues fileTransferValues = new ContentValues();
-        assertThat(mContentResolver.insert(Uri.parse("content://rcs/message/3/file_transfer"),
-                fileTransferValues)).isEqualTo(Uri.parse("content://rcs/file_transfer/1"));
-
-        // insert an alias change event
-        ContentValues eventValues = new ContentValues();
-        eventValues.put(NEW_ALIAS_COLUMN, "new alias");
-        assertThat(
-                mContentResolver.insert(Uri.parse("content://rcs/participant/1/alias_change_event"),
-                        eventValues)).isEqualTo(Uri.parse(
-                "content://rcs/participant/1/alias_change_event/1"));
-
-        // create a group name change event
-        eventValues.clear();
-        eventValues.put(NEW_NAME_COLUMN, "new name");
-        assertThat(mContentResolver.insert(
-                Uri.parse("content://rcs/group_thread/2/name_changed_event"),
-                eventValues)).isEqualTo(Uri.parse(
-                "content://rcs/group_thread/2/name_changed_event/1"));
-    }
-
-    @After
-    public void tearDown() {
-        mRcsProvider.tearDown();
-    }
-
-    @Test
-    public void testDelete1To1ThreadWithId() {
-        assertThat(mContentResolver.delete(Uri.parse("content://rcs/p2p_thread/1"), null,
-                null)).isEqualTo(1);
-        assertDeletionViaQuery("content://rcs/p2p_thread/1");
-    }
-
-    @Test
-    public void testDelete1To1ThreadWithSelection() {
-        assertThat(mContentResolver.delete(Uri.parse("content://rcs/p2p_thread"),
-                "rcs_fallback_thread_id=1", null)).isEqualTo(1);
-        assertDeletionViaQuery("content://rcs/p2p_thread/1");
-    }
-
-    @Test
-    public void testDeleteGroupThreadWithId() {
-        assertThat(mContentResolver.delete(Uri.parse("content://rcs/group_thread/2"), null,
-                null)).isEqualTo(1);
-        assertDeletionViaQuery("content://rcs/group_thread/2");
-    }
-
-    @Test
-    public void testDeleteGroupThreadWithSelection() {
-        assertThat(mContentResolver.delete(Uri.parse("content://rcs/group_thread"),
-                "group_name=\"name\"", null)).isEqualTo(1);
-        assertDeletionViaQuery("content://rcs/group_thread/1");
-    }
-
-    @Test
-    public void testDeleteParticipantWithIdWhileParticipatingInAThread() {
-        assertThat(mContentResolver.delete(Uri.parse("content://rcs/participant/1"), null,
-                null)).isEqualTo(0);
-    }
-
-    @Test
-    public void testDeleteParticipantAfterLeavingThreads() {
-        // leave the first thread
-        assertThat(mContentResolver.delete(Uri.parse("content://rcs/group_thread/2/participant/1"),
-                null, null)).isEqualTo(1);
-
-        // try deleting the participant. It should fail
-        assertThat(mContentResolver.delete(Uri.parse("content://rcs/participant/1"), null,
-                null)).isEqualTo(0);
-
-        // delete the p2p thread
-        assertThat(mContentResolver.delete(Uri.parse("content://rcs/p2p_thread/1"), null,
-                null)).isEqualTo(1);
-
-        // try deleting the participant. It should succeed
-        assertThat(mContentResolver.delete(Uri.parse("content://rcs/participant/1"), null,
-                null)).isEqualTo(1);
-        assertDeletionViaQuery("content://rcs/participant/1");
-    }
-
-    @Test
-    public void testDeleteParticipantWithSelectionFails() {
-        assertThat(
-                mContentResolver.delete(Uri.parse("content://rcs/participant"), "rcs_alias=\"Bob\"",
-                        null)).isEqualTo(0);
-    }
-
-    @Test
-    public void testDeleteParticipantFrom1To1ThreadFails() {
-        assertThat(
-                mContentResolver.delete(Uri.parse("content://rcs/p2p_thread/1/participant/1"), null,
-                        null)).isEqualTo(0);
-    }
-
-    @Test
-    public void testDeleteParticipantFromGroupThread() {
-        assertThat(mContentResolver.delete(Uri.parse("content://rcs/group_thread/2/participant/1"),
-                null, null)).isEqualTo(1);
-        assertDeletionViaQuery("content://rcs/group_thread/2/participant");
-    }
-
-    @Test
-    public void testDeleteParticipantFromGroupThreadWithSelectionFails() {
-        assertThat(mContentResolver.delete(Uri.parse("content://rcs/group_thread/2/participant"),
-                "rcs_alias=?", new String[]{"Bob"})).isEqualTo(0);
-    }
-
-    @Test
-    public void testDeleteMessagesUsingUnifiedMessageViewFails() {
-        assertThat(mContentResolver.delete(Uri.parse("content://rcs/message/1"), null,
-                null)).isEqualTo(0);
-    }
-
-    @Test
-    public void testDeleteMessagesUsingThreadUrisFails() {
-        assertThat(mContentResolver.delete(Uri.parse("content://rcs/p2p_thread/1/message/1"), null,
-                null)).isEqualTo(0);
-        assertThat(
-                mContentResolver.delete(Uri.parse("content://rcs/p2p_thread/1/incoming_message/1"),
-                        null, null)).isEqualTo(0);
-    }
-
-    @Test
-    @Ignore // TODO: fix and un-ignore
-    public void testDeleteMessage() {
-        // verify there exists 4 messages
-        Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/message"), null, null,
-                null);
-        assertThat(cursor.getCount()).isEqualTo(4);
-        cursor.close();
-
-        // delete 2 of them
-        assertThat(mContentResolver.delete(Uri.parse("content://rcs/incoming_message/1"), null,
-                null)).isEqualTo(1);
-        assertThat(mContentResolver.delete(Uri.parse("content://rcs/outgoing_message/4"), null,
-                null)).isEqualTo(1);
-
-        // verify that only 2 messages are left
-        cursor = mContentResolver.query(Uri.parse("content://rcs/message"), null, null, null);
-        assertThat(cursor.getCount()).isEqualTo(2);
-        cursor.close();
-
-        // verify that entries in common table is deleted and only messages with id's 2 and 3 remain
-        SQLiteDatabase db = mRcsProvider.getWritableDatabase();
-        cursor = db.query(RCS_MESSAGE_TABLE, null, null, null, null, null, null);
-        assertThat(cursor.getCount()).isEqualTo(2);
-
-        cursor.moveToNext();
-        assertThat(cursor.getInt(0)).isEqualTo(2);
-        cursor.moveToNext();
-        assertThat(cursor.getInt(0)).isEqualTo(3);
-        cursor.close();
-    }
-
-    @Test
-    public void testDeleteFileTransfer() {
-        assertThat(mContentResolver.delete(Uri.parse("content://rcs/file_transfer/1"), null,
-                null)).isEqualTo(1);
-        assertDeletionViaQuery("content://rcs/file_transfer/1");
-    }
-
-    @Test
-    public void testDeleteParticipantEvent() {
-        assertThat(mContentResolver.delete(Uri.parse(
-                "content://rcs/participant/1/alias_change_event/1"), null, null)).isEqualTo(1);
-
-        // try deleting again and verify nothing is deleted
-        // TODO - convert to query once querying is in place
-        assertThat(mContentResolver.delete(Uri.parse(
-                "content://rcs/participant/1/alias_change_event/1"), null, null)).isEqualTo(0);
-    }
-
-    @Test
-    public void testDeleteGroupThreadEvent() {
-        assertThat(mContentResolver.delete(Uri.parse(
-                "content://rcs/group_thread/2/name_changed_event/1"), null, null)).isEqualTo(1);
-
-        // try deleting again and verify nothing is deleted
-        // TODO - convert to query once querying is in place
-        assertThat(mContentResolver.delete(Uri.parse(
-                "content://rcs/group_thread/2/name_changed_event/1"), null, null)).isEqualTo(0);
-    }
-
-    private void assertDeletionViaQuery(String queryUri) {
-        Cursor cursor = mContentResolver.query(Uri.parse(queryUri), null, null, null);
-        assertThat(cursor.getCount()).isEqualTo(0);
-        cursor.close();
-    }
-}
diff --git a/tests/src/com/android/providers/telephony/RcsProviderHelper.java b/tests/src/com/android/providers/telephony/RcsProviderHelper.java
deleted file mode 100644
index 5a7f9a0..0000000
--- a/tests/src/com/android/providers/telephony/RcsProviderHelper.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2019 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 static android.provider.Telephony.RcsColumns.Rcs1To1ThreadColumns.FALLBACK_THREAD_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.RCS_PARTICIPANT_ID_COLUMN;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.net.Uri;
-
-class RcsProviderHelper {
-    /**
-     * Sets up a 1-to-1 thread with a participant ID of 1 and a fallback thread ID of 1.
-     *
-     * @return the {@link Uri} of the newly inserted row
-     */
-    static Uri setup1To1Thread(ContentResolver contentResolver) {
-        return setup1To1Thread(contentResolver, 1, 1);
-    }
-
-    static Uri setup1To1Thread(
-            ContentResolver contentResolver, int participantId, int fallbackThreadId) {
-        ContentValues insertValues = new ContentValues();
-        Uri insertionUri = Uri.parse("content://rcs/p2p_thread");
-        insertValues.put(RCS_PARTICIPANT_ID_COLUMN, participantId);
-
-        Uri rowUri = contentResolver.insert(insertionUri, insertValues);
-        assertThat(rowUri).isNotNull();
-
-        ContentValues updateValues = new ContentValues();
-        updateValues.put(FALLBACK_THREAD_ID_COLUMN, fallbackThreadId);
-        assertThat(contentResolver.update(rowUri, updateValues, null, null))
-                .isEqualTo(1);
-
-        return rowUri;
-    }
-
-}
diff --git a/tests/src/com/android/providers/telephony/RcsProviderInsertTest.java b/tests/src/com/android/providers/telephony/RcsProviderInsertTest.java
deleted file mode 100644
index 1a48a49..0000000
--- a/tests/src/com/android/providers/telephony/RcsProviderInsertTest.java
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * 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 static android.provider.Telephony.RcsColumns.RcsGroupThreadColumns.CONFERENCE_URI_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsGroupThreadColumns.GROUP_ICON_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsGroupThreadColumns.GROUP_NAME_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.GLOBAL_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.CANONICAL_ADDRESS_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.RCS_ALIAS_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantEventColumns.NEW_ALIAS_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.NEW_NAME_COLUMN;
-
-import static com.android.providers.telephony.RcsProviderHelper.setup1To1Thread;
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.net.Uri;
-import android.test.mock.MockContentResolver;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
-
-@RunWith(AndroidJUnit4.class)
-public class RcsProviderInsertTest {
-    private MockContentResolver mContentResolver;
-    private RcsProviderTestable mRcsProvider;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mRcsProvider = new RcsProviderTestable();
-        RcsProviderTestable.MockContextWithProvider
-                context = new RcsProviderTestable.MockContextWithProvider(mRcsProvider);
-        mContentResolver = context.getContentResolver();
-    }
-
-    @After
-    public void tearDown() {
-        mRcsProvider.tearDown();
-    }
-
-    @Test
-    public void testInsertUnifiedThreadFails() {
-        assertThat(mContentResolver.insert(Uri.parse("content://rcs/thread"), null)).isNull();
-    }
-
-    @Test
-    public void testDuplicate1To1ThreadInsertion() {
-        Uri uri = setup1To1Thread(mContentResolver);
-
-        assertThat(mContentResolver.insert(uri, null)).isNull();
-    }
-
-    @Test
-    public void testInsertGroupThread() {
-        ContentValues contentValues = new ContentValues(3);
-        contentValues.put(CONFERENCE_URI_COLUMN, "conference uri");
-        contentValues.put(GROUP_NAME_COLUMN, "group name");
-        contentValues.put(GROUP_ICON_COLUMN, "groupIcon");
-        assertThat(mContentResolver.insert(Uri.parse("content://rcs/group_thread"),
-                contentValues)).isEqualTo(Uri.parse("content://rcs/group_thread/1"));
-    }
-
-    @Test
-    public void testInsertParticipant() {
-        ContentValues contentValues = new ContentValues();
-        contentValues.put(CANONICAL_ADDRESS_ID_COLUMN, 6);
-        contentValues.put(RCS_ALIAS_COLUMN, "Alias");
-
-        Uri uri = mContentResolver.insert(Uri.parse("content://rcs/participant"), contentValues);
-        assertThat(uri).isEqualTo(Uri.parse("content://rcs/participant/1"));
-    }
-
-    @Test
-    public void testInsertParticipantIntoGroupThread() {
-        // create a participant
-        ContentValues contentValues = new ContentValues();
-        contentValues.put(CANONICAL_ADDRESS_ID_COLUMN, 23);
-        mContentResolver.insert(Uri.parse("content://rcs/participant"), contentValues);
-
-        // create a thread
-        ContentValues values = new ContentValues(1);
-        values.put(GROUP_NAME_COLUMN, "Group");
-        mContentResolver.insert(Uri.parse("content://rcs/group_thread"), values);
-
-        // add participant to the thread
-        Uri uri = Uri.parse("content://rcs/group_thread/1/participant/1");
-        assertThat(mContentResolver.insert(uri, null)).isEqualTo(uri);
-
-        // assert that adding again fails
-        assertThat(mContentResolver.insert(uri, null)).isNull();
-    }
-
-    @Test
-    public void testInsertMessageFails() {
-        ContentValues contentValues = new ContentValues();
-        contentValues.put(GLOBAL_ID_COLUMN, "global RCS id");
-
-        // try inserting messages without threads
-        assertThat(mContentResolver.insert(Uri.parse("content://rcs/message"),
-                contentValues)).isNull();
-        assertThat(mContentResolver.insert(Uri.parse("content://rcs/message/6"),
-                contentValues)).isNull();
-        assertThat(mContentResolver.insert(Uri.parse("content://rcs/incoming_message"),
-                contentValues)).isNull();
-        assertThat(mContentResolver.insert(Uri.parse("content://rcs/incoming_message/12"),
-                contentValues)).isNull();
-        assertThat(mContentResolver.insert(Uri.parse("content://rcs/outgoing_message"),
-                contentValues)).isNull();
-        assertThat(mContentResolver.insert(Uri.parse("content://rcs/outgoing_message/18"),
-                contentValues)).isNull();
-
-        // try inserting into unified thread view
-        assertThat(mContentResolver.insert(Uri.parse("content://rcs/thread/5/incoming_message"),
-                contentValues)).isNull();
-        assertThat(mContentResolver.insert(Uri.parse("content://rcs/thread/5/outgoing_message"),
-                contentValues)).isNull();
-    }
-
-    @Test
-    @Ignore // TODO: fix and un-ignore
-    public void testInsertMessageIntoThread() {
-        // create two threads
-        setup1To1Thread(mContentResolver);
-        ContentValues values = new ContentValues();
-        assertThat(mContentResolver.insert(Uri.parse("content://rcs/group_thread"),
-                values)).isNotNull();
-
-        // add messages to threads
-        assertThat(mContentResolver.insert(Uri.parse("content://rcs/p2p_thread/1/incoming_message"),
-                values)).isEqualTo(Uri.parse("content://rcs/p2p_thread/1/incoming_message/1"));
-        assertThat(mContentResolver.insert(Uri.parse("content://rcs/p2p_thread/1/outgoing_message"),
-                values)).isEqualTo(Uri.parse("content://rcs/p2p_thread/1/outgoing_message/2"));
-        assertThat(
-                mContentResolver.insert(Uri.parse("content://rcs/group_thread/2/incoming_message"),
-                        values)).isEqualTo(
-                Uri.parse("content://rcs/group_thread/2/incoming_message/3"));
-        assertThat(
-                mContentResolver.insert(Uri.parse("content://rcs/group_thread/2/outgoing_message"),
-                        values)).isEqualTo(
-                Uri.parse("content://rcs/group_thread/2/outgoing_message/4"));
-
-        // assert that they are accessible in messages table
-        Cursor messageCursor = mContentResolver.query(Uri.parse("content://rcs/message"), null,
-                null, null, null);
-        assertThat(messageCursor.getCount()).isEqualTo(4);
-    }
-
-    @Test
-    public void testInsertMessageDelivery() {
-        setup1To1Thread(mContentResolver);
-
-        ContentValues values = new ContentValues();
-
-        // add an outgoing message to the thread
-        assertThat(mContentResolver.insert(Uri.parse("content://rcs/p2p_thread/1/outgoing_message"),
-                values)).isEqualTo(Uri.parse("content://rcs/p2p_thread/1/outgoing_message/1"));
-
-        // add a delivery to the outgoing message
-        assertThat(mContentResolver.insert(Uri.parse("content://rcs/outgoing_message/1/delivery/1"),
-                values)).isEqualTo(Uri.parse("content://rcs/outgoing_message/1/delivery/1"));
-    }
-
-    @Test
-    public void testInsertFileTransfer() {
-        setup1To1Thread(mContentResolver);
-
-        ContentValues values = new ContentValues();
-
-        // add an outgoing message to the thread
-        assertThat(mContentResolver.insert(Uri.parse("content://rcs/p2p_thread/1/outgoing_message"),
-                values)).isEqualTo(Uri.parse("content://rcs/p2p_thread/1/outgoing_message/1"));
-
-        // add a file transfer to the message
-        assertThat(mContentResolver.insert(Uri.parse("content://rcs/message/1/file_transfer"),
-                values)).isEqualTo(Uri.parse("content://rcs/file_transfer/1"));
-    }
-
-    @Test
-    public void testInsertParticipantEvent() {
-        // create a participant
-        ContentValues contentValues = new ContentValues();
-        contentValues.put(CANONICAL_ADDRESS_ID_COLUMN, 23);
-        mContentResolver.insert(Uri.parse("content://rcs/participant"), contentValues);
-
-        // insert an alias change event
-        ContentValues eventValues = new ContentValues();
-        eventValues.put(NEW_ALIAS_COLUMN, "new alias");
-        assertThat(
-                mContentResolver.insert(Uri.parse("content://rcs/participant/1/alias_change_event"),
-                        eventValues)).isEqualTo(Uri.parse(
-                "content://rcs/participant/1/alias_change_event/1"));
-    }
-
-    @Test
-    public void testInsertGroupThreadEvent() {
-        // create a group thread
-        ContentValues contentValues = new ContentValues();
-        assertThat(mContentResolver.insert(Uri.parse("content://rcs/group_thread"),
-                contentValues)).isEqualTo(Uri.parse("content://rcs/group_thread/1"));
-
-        // create a group name change event
-        ContentValues eventValues = new ContentValues();
-        eventValues.put(NEW_NAME_COLUMN, "new name");
-        assertThat(mContentResolver.insert(
-                Uri.parse("content://rcs/group_thread/1/name_changed_event"),
-                eventValues)).isEqualTo(Uri.parse(
-                "content://rcs/group_thread/1/name_changed_event/1"));
-    }
-}
diff --git a/tests/src/com/android/providers/telephony/RcsProviderQueryTest.java b/tests/src/com/android/providers/telephony/RcsProviderQueryTest.java
deleted file mode 100644
index f0579ea..0000000
--- a/tests/src/com/android/providers/telephony/RcsProviderQueryTest.java
+++ /dev/null
@@ -1,582 +0,0 @@
-/*
- * 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 static android.provider.Telephony.RcsColumns.RcsEventTypes.PARTICIPANT_JOINED_EVENT_TYPE;
-import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.FILE_SIZE_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.SESSION_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsGroupThreadColumns.GROUP_NAME_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.MESSAGE_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.MESSAGE_TEXT_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.MESSAGE_TYPE_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.ORIGINATION_TIMESTAMP_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.CANONICAL_ADDRESS_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.RCS_ALIAS_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.RCS_PARTICIPANT_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsThreadColumns.RCS_THREAD_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.DESTINATION_PARTICIPANT_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.EVENT_TYPE_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.NEW_NAME_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.SOURCE_PARTICIPANT_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsUnifiedThreadColumns.THREAD_TYPE_COLUMN;
-import static android.telephony.ims.RcsEventQueryParams.EVENT_QUERY_PARAMETERS_KEY;
-import static android.telephony.ims.RcsEventQueryParams.GROUP_THREAD_NAME_CHANGED_EVENT;
-import static android.telephony.ims.RcsMessageQueryParams.MESSAGE_QUERY_PARAMETERS_KEY;
-import static android.telephony.ims.RcsParticipantQueryParams.PARTICIPANT_QUERY_PARAMETERS_KEY;
-import static android.telephony.ims.RcsQueryContinuationToken.QUERY_CONTINUATION_TOKEN;
-import static android.telephony.ims.RcsThreadQueryParams.THREAD_QUERY_PARAMETERS_KEY;
-
-import static com.android.providers.telephony.RcsProviderHelper.setup1To1Thread;
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-import android.telephony.ims.RcsEventQueryParams;
-import android.telephony.ims.RcsGroupThread;
-import android.telephony.ims.RcsMessageQueryParams;
-import android.telephony.ims.RcsParticipantQueryParams;
-import android.telephony.ims.RcsQueryContinuationToken;
-import android.telephony.ims.RcsThreadQueryParams;
-import android.test.mock.MockContentResolver;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.providers.telephony.RcsProviderTestable.MockContextWithProvider;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
-
-@RunWith(AndroidJUnit4.class)
-public class RcsProviderQueryTest {
-    private MockContentResolver mContentResolver;
-    private RcsProviderTestable mRcsProvider;
-
-    private static final String GROUP_NAME = "group name";
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mRcsProvider = new RcsProviderTestable();
-        MockContextWithProvider context = new MockContextWithProvider(mRcsProvider);
-        mContentResolver = context.getContentResolver();
-
-        // insert two participants
-        Uri participantUri = Uri.parse("content://rcs/participant");
-        ContentValues contentValues = new ContentValues();
-        contentValues.put(CANONICAL_ADDRESS_ID_COLUMN, 99);
-        contentValues.put(RCS_ALIAS_COLUMN, "Some alias");
-        mContentResolver.insert(participantUri, contentValues);
-
-        contentValues.clear();
-        contentValues.put(CANONICAL_ADDRESS_ID_COLUMN, 100);
-        contentValues.put(RCS_ALIAS_COLUMN, "Some other alias");
-        mContentResolver.insert(participantUri, contentValues);
-
-        // insert two 1 to 1 threads
-        setup1To1Thread(mContentResolver, 1, 1);
-        setup1To1Thread(mContentResolver, 2, 2);
-
-        // insert one group thread
-        ContentValues groupContentValues = new ContentValues(1);
-        groupContentValues.put(GROUP_NAME_COLUMN, GROUP_NAME);
-        assertThat(mContentResolver.insert(Uri.parse("content://rcs/group_thread"),
-                groupContentValues)).isEqualTo(Uri.parse("content://rcs/group_thread/3"));
-
-        // put participants into the group
-        mContentResolver.insert(Uri.parse("content://rcs/group_thread/3/participant/1"), null);
-        mContentResolver.insert(Uri.parse("content://rcs/group_thread/3/participant/2"), null);
-
-        // insert two messages into first thread, leave the second one empty, insert one into group
-        // thread
-        ContentValues messageValues = new ContentValues();
-
-        messageValues.put(ORIGINATION_TIMESTAMP_COLUMN, 300);
-        messageValues.put(MESSAGE_TEXT_COLUMN, "Old message");
-        assertThat(mContentResolver.insert(Uri.parse("content://rcs/p2p_thread/1/incoming_message"),
-                messageValues)).isEqualTo(
-                Uri.parse("content://rcs/p2p_thread/1/incoming_message/1"));
-
-        messageValues.clear();
-        messageValues.put(ORIGINATION_TIMESTAMP_COLUMN, 400);
-        messageValues.put(MESSAGE_TEXT_COLUMN, "New message");
-        assertThat(mContentResolver.insert(Uri.parse("content://rcs/p2p_thread/1/outgoing_message"),
-                messageValues)).isEqualTo(
-                Uri.parse("content://rcs/p2p_thread/1/outgoing_message/2"));
-
-        messageValues.clear();
-        messageValues.put(ORIGINATION_TIMESTAMP_COLUMN, 200);
-        messageValues.put(MESSAGE_TEXT_COLUMN, "Group message");
-        assertThat(
-                mContentResolver.insert(Uri.parse("content://rcs/group_thread/3/incoming_message"),
-                        messageValues)).isEqualTo(
-                Uri.parse("content://rcs/group_thread/3/incoming_message/3"));
-
-        // Add two events to the group thread
-        ContentValues eventValues = new ContentValues();
-        eventValues.put(NEW_NAME_COLUMN, "New group name");
-        assertThat(mContentResolver.insert(
-                Uri.parse("content://rcs/group_thread/3/name_changed_event"),
-                eventValues)).isEqualTo(
-                Uri.parse("content://rcs/group_thread/3/name_changed_event/1"));
-
-        eventValues.clear();
-        eventValues.put(SOURCE_PARTICIPANT_ID_COLUMN, 1);
-        eventValues.put(DESTINATION_PARTICIPANT_ID_COLUMN, 2);
-        assertThat(mContentResolver.insert(
-                Uri.parse("content://rcs/group_thread/3/participant_joined_event"),
-                eventValues)).isEqualTo(
-                Uri.parse("content://rcs/group_thread/3/participant_joined_event/2"));
-    }
-
-    @After
-    public void tearDown() {
-        mRcsProvider.tearDown();
-    }
-
-    @Test
-    public void testCanQueryUnifiedThreads() {
-        RcsThreadQueryParams queryParameters = new RcsThreadQueryParams.Builder().build();
-        Bundle bundle = new Bundle();
-        bundle.putParcelable(THREAD_QUERY_PARAMETERS_KEY, queryParameters);
-
-        Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/thread"),
-                null, bundle, null);
-        assertThat(cursor.getCount()).isEqualTo(3);
-
-        cursor.moveToNext();
-        assertThat(cursor.getInt(cursor.getColumnIndex(THREAD_TYPE_COLUMN))).isEqualTo(1);
-        assertThat(cursor.getString(cursor.getColumnIndex(GROUP_NAME_COLUMN))).isEqualTo(
-                GROUP_NAME);
-        assertThat(cursor.getInt(cursor.getColumnIndex(ORIGINATION_TIMESTAMP_COLUMN))).isEqualTo(
-                200);
-        assertThat(cursor.getString(cursor.getColumnIndex(MESSAGE_TEXT_COLUMN))).isEqualTo(
-                "Group message");
-        cursor.moveToNext();
-        assertThat(cursor.getInt(cursor.getColumnIndex(THREAD_TYPE_COLUMN))).isEqualTo(0);
-        assertThat(cursor.getString(cursor.getColumnIndex(GROUP_NAME_COLUMN))).isEqualTo(null);
-        assertThat(cursor.getInt(cursor.getColumnIndex(ORIGINATION_TIMESTAMP_COLUMN))).isEqualTo(0);
-        assertThat(cursor.getString(cursor.getColumnIndex(MESSAGE_TEXT_COLUMN))).isEqualTo(null);
-        cursor.moveToNext();
-        assertThat(cursor.getInt(cursor.getColumnIndex(THREAD_TYPE_COLUMN))).isEqualTo(0);
-        assertThat(cursor.getString(cursor.getColumnIndex(GROUP_NAME_COLUMN))).isEqualTo(null);
-        assertThat(cursor.getInt(cursor.getColumnIndex(ORIGINATION_TIMESTAMP_COLUMN))).isEqualTo(
-                400);
-        assertThat(cursor.getString(cursor.getColumnIndex(MESSAGE_TEXT_COLUMN))).isEqualTo(
-                "New message");
-    }
-
-    @Test
-    public void testCanQueryUnifiedThreadsWithLimitAndSorting() {
-        RcsThreadQueryParams queryParameters = new RcsThreadQueryParams.Builder()
-                .setThreadType(RcsThreadQueryParams.THREAD_TYPE_1_TO_1).setResultLimit(1)
-                .setSortProperty(RcsThreadQueryParams.SORT_BY_TIMESTAMP).setSortDirection(true)
-                .build();
-        Bundle bundle = new Bundle();
-        bundle.putParcelable(THREAD_QUERY_PARAMETERS_KEY, queryParameters);
-
-        Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/thread"),
-                null, bundle, null);
-        assertThat(cursor.getCount()).isEqualTo(1);
-
-        cursor.moveToNext();
-        assertThat(cursor.getInt(cursor.getColumnIndex(THREAD_TYPE_COLUMN))).isEqualTo(0);
-        assertThat(cursor.getString(cursor.getColumnIndex(GROUP_NAME_COLUMN))).isEqualTo(null);
-        assertThat(cursor.getInt(cursor.getColumnIndex(ORIGINATION_TIMESTAMP_COLUMN))).isEqualTo(0);
-        assertThat(cursor.getString(cursor.getColumnIndex(MESSAGE_TEXT_COLUMN))).isEqualTo(null);
-    }
-
-    @Test
-    public void testCanContinueThreadQuery() {
-        // Limit results to 1.
-        RcsThreadQueryParams queryParameters =
-                new RcsThreadQueryParams.Builder().setResultLimit(1).build();
-        Bundle bundle = new Bundle();
-        bundle.putParcelable(THREAD_QUERY_PARAMETERS_KEY, queryParameters);
-
-        // Perform an initial query, verify first thread is returned
-        Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/thread"), null, bundle,
-                null);
-        assertThat(cursor.getCount()).isEqualTo(1);
-
-        cursor.moveToNext();
-        assertThat(cursor.getInt(cursor.getColumnIndex(THREAD_TYPE_COLUMN))).isEqualTo(1);
-        assertThat(cursor.getString(cursor.getColumnIndex(GROUP_NAME_COLUMN))).isEqualTo(
-                GROUP_NAME);
-        assertThat(cursor.getInt(cursor.getColumnIndex(ORIGINATION_TIMESTAMP_COLUMN))).isEqualTo(
-                200);
-        assertThat(cursor.getString(cursor.getColumnIndex(MESSAGE_TEXT_COLUMN))).isEqualTo(
-                "Group message");
-
-        // Put the continuation token in the bundle to do a follow up query
-        RcsQueryContinuationToken continuationToken = cursor.getExtras().getParcelable(
-                QUERY_CONTINUATION_TOKEN);
-        bundle.clear();
-        bundle.putParcelable(QUERY_CONTINUATION_TOKEN, continuationToken);
-        cursor.close();
-
-        cursor = mContentResolver.query(Uri.parse("content://rcs/thread"), null, bundle,
-                null);
-        assertThat(cursor.getCount()).isEqualTo(1);
-        cursor.moveToNext();
-        assertThat(cursor.getInt(cursor.getColumnIndex(THREAD_TYPE_COLUMN))).isEqualTo(0);
-        assertThat(cursor.getString(cursor.getColumnIndex(GROUP_NAME_COLUMN))).isEqualTo(null);
-        assertThat(cursor.getInt(cursor.getColumnIndex(ORIGINATION_TIMESTAMP_COLUMN))).isEqualTo(0);
-        assertThat(cursor.getString(cursor.getColumnIndex(MESSAGE_TEXT_COLUMN))).isEqualTo(null);
-        cursor.close();
-
-        // Put the continuation token in the bundle to do a follow up query again, verify third
-        // thread is returned
-        continuationToken = cursor.getExtras().getParcelable(QUERY_CONTINUATION_TOKEN);
-        bundle.clear();
-        bundle.putParcelable(QUERY_CONTINUATION_TOKEN, continuationToken);
-        cursor = mContentResolver.query(Uri.parse("content://rcs/thread"), null, bundle,
-                null);
-        assertThat(cursor.getCount()).isEqualTo(1);
-        cursor.moveToNext();
-        assertThat(cursor.getInt(cursor.getColumnIndex(THREAD_TYPE_COLUMN))).isEqualTo(0);
-        assertThat(cursor.getString(cursor.getColumnIndex(GROUP_NAME_COLUMN))).isEqualTo(null);
-        assertThat(cursor.getInt(cursor.getColumnIndex(ORIGINATION_TIMESTAMP_COLUMN))).isEqualTo(
-                400);
-        assertThat(cursor.getString(cursor.getColumnIndex(MESSAGE_TEXT_COLUMN))).isEqualTo(
-                "New message");
-        cursor.close();
-    }
-
-    @Test
-    public void testQuery1To1Threads() {
-        // verify two threads are returned in the query
-        Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/p2p_thread"),
-                new String[]{RCS_THREAD_ID_COLUMN}, null, null, null);
-        assertThat(cursor.getCount()).isEqualTo(2);
-    }
-
-    @Test
-    public void testQueryGroupThreads() {
-        // verify one thread is returned in the query
-        Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/group_thread"),
-                new String[]{GROUP_NAME_COLUMN}, null, null, null);
-        assertThat(cursor.getCount()).isEqualTo(1);
-
-        cursor.moveToNext();
-        assertThat(cursor.getString(0)).isEqualTo(GROUP_NAME);
-    }
-
-    @Test
-    public void testQueryParticipant() {
-        RcsParticipantQueryParams queryParameters = new RcsParticipantQueryParams.Builder()
-                .build();
-
-        Bundle bundle = new Bundle();
-        bundle.putParcelable(PARTICIPANT_QUERY_PARAMETERS_KEY, queryParameters);
-
-        Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/participant"), null, bundle,
-                null);
-        assertThat(cursor.getCount()).isEqualTo(2);
-
-        cursor.moveToNext();
-        assertThat(cursor.getInt(cursor.getColumnIndex(RCS_PARTICIPANT_ID_COLUMN))).isEqualTo(2);
-        assertThat(cursor.getInt(cursor.getColumnIndex(CANONICAL_ADDRESS_ID_COLUMN))).isEqualTo(
-                100);
-        assertThat(cursor.getString(cursor.getColumnIndex(RCS_ALIAS_COLUMN))).isEqualTo(
-                "Some other alias");
-
-        cursor.moveToNext();
-        assertThat(cursor.getInt(cursor.getColumnIndex(RCS_PARTICIPANT_ID_COLUMN))).isEqualTo(1);
-        assertThat(cursor.getInt(cursor.getColumnIndex(CANONICAL_ADDRESS_ID_COLUMN))).isEqualTo(99);
-        assertThat(cursor.getString(cursor.getColumnIndex(RCS_ALIAS_COLUMN))).isEqualTo(
-                "Some alias");
-    }
-
-    @Test
-    public void testQueryParticipantWithContinuation() {
-        Uri participantUri = Uri.parse("content://rcs/participant");
-
-        // Perform the initial query
-        RcsParticipantQueryParams queryParameters =
-                new RcsParticipantQueryParams.Builder().setAliasLike("%ali%").setSortProperty(
-                        RcsParticipantQueryParams.SORT_BY_ALIAS).setSortDirection(true)
-                        .setResultLimit(1).build();
-
-        Bundle bundle = new Bundle();
-        bundle.putParcelable(PARTICIPANT_QUERY_PARAMETERS_KEY, queryParameters);
-
-        Cursor cursor = mContentResolver.query(participantUri, null, bundle, null);
-        assertThat(cursor.getCount()).isEqualTo(1);
-
-        cursor.moveToNext();
-        assertThat(cursor.getInt(0)).isEqualTo(1);
-        assertThat(cursor.getInt(1)).isEqualTo(99);
-        assertThat(cursor.getString(2)).isEqualTo("Some alias");
-
-        // Perform the continuation query
-        RcsQueryContinuationToken continuationToken = cursor.getExtras().getParcelable(
-                QUERY_CONTINUATION_TOKEN);
-        bundle.clear();
-        bundle.putParcelable(QUERY_CONTINUATION_TOKEN, continuationToken);
-
-        cursor = mContentResolver.query(participantUri, null, bundle, null);
-        assertThat(cursor.getCount()).isEqualTo(1);
-
-        cursor.moveToNext();
-        assertThat(cursor.getInt(0)).isEqualTo(2);
-        assertThat(cursor.getInt(1)).isEqualTo(100);
-        assertThat(cursor.getString(2)).isEqualTo("Some other alias");
-
-        // Perform the continuation query to verify no entries left
-        continuationToken = cursor.getExtras().getParcelable(QUERY_CONTINUATION_TOKEN);
-        bundle.clear();
-        bundle.putParcelable(QUERY_CONTINUATION_TOKEN, continuationToken);
-
-        cursor = mContentResolver.query(participantUri, null, bundle, null);
-        assertThat(cursor.getCount()).isEqualTo(0);
-        continuationToken = cursor.getExtras().getParcelable(QUERY_CONTINUATION_TOKEN);
-        assertThat(continuationToken).isNull();
-    }
-
-    @Test
-    public void testQueryGroupParticipants() {
-        // TODO - implement
-    }
-
-    @Test
-    @Ignore // TODO: fix and un-ignore
-    public void testQueryEvents() {
-        RcsEventQueryParams queryParameters = new RcsEventQueryParams.Builder().build();
-
-        Bundle bundle = new Bundle();
-        bundle.putParcelable(EVENT_QUERY_PARAMETERS_KEY, queryParameters);
-
-        Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/event"), null, bundle,
-                null);
-        assertThat(cursor.getCount()).isEqualTo(2);
-
-        cursor.moveToNext();
-        assertThat(cursor.getInt(cursor.getColumnIndex(EVENT_TYPE_COLUMN))).isEqualTo(
-                PARTICIPANT_JOINED_EVENT_TYPE);
-        assertThat(cursor.getInt(cursor.getColumnIndex(SOURCE_PARTICIPANT_ID_COLUMN))).isEqualTo(
-                1);
-        assertThat(cursor.getInt(cursor.getColumnIndex(DESTINATION_PARTICIPANT_ID_COLUMN))).isEqualTo(
-                2);
-
-        cursor.moveToNext();
-        assertThat(cursor.getInt(cursor.getColumnIndex(EVENT_TYPE_COLUMN))).isEqualTo(
-                GROUP_THREAD_NAME_CHANGED_EVENT);
-        assertThat(cursor.getString(cursor.getColumnIndex(NEW_NAME_COLUMN))).isEqualTo(
-                "New group name");
-    }
-
-    @Test
-    @Ignore // TODO: fix and un-ignore
-    public void testQueryEventsWithContinuation() {
-        RcsEventQueryParams queryParameters =
-                new RcsEventQueryParams.Builder().setResultLimit(1).setSortDirection(true)
-                        .build();
-
-        Bundle bundle = new Bundle();
-        bundle.putParcelable(EVENT_QUERY_PARAMETERS_KEY, queryParameters);
-
-        Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/event"), null, bundle,
-                null);
-        assertThat(cursor.getCount()).isEqualTo(1);
-
-        cursor.moveToNext();
-        assertThat(cursor.getInt(cursor.getColumnIndex(EVENT_TYPE_COLUMN))).isEqualTo(
-                GROUP_THREAD_NAME_CHANGED_EVENT);
-        assertThat(cursor.getString(cursor.getColumnIndex(NEW_NAME_COLUMN))).isEqualTo(
-                "New group name");
-    }
-
-    @Test
-    @Ignore // TODO: fix and un-ignore
-    public void testQueryEventsWithTypeLimitation() {
-        RcsEventQueryParams queryParameters =
-                new RcsEventQueryParams.Builder().setEventType(
-                        GROUP_THREAD_NAME_CHANGED_EVENT).build();
-        Bundle bundle = new Bundle();
-        bundle.putParcelable(EVENT_QUERY_PARAMETERS_KEY, queryParameters);
-
-        Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/event"), null, bundle,
-                null);
-        assertThat(cursor.getCount()).isEqualTo(1);
-
-        cursor.moveToNext();
-        assertThat(cursor.getInt(cursor.getColumnIndex(EVENT_TYPE_COLUMN))).isEqualTo(
-                GROUP_THREAD_NAME_CHANGED_EVENT);
-        assertThat(cursor.getString(cursor.getColumnIndex(NEW_NAME_COLUMN))).isEqualTo(
-                "New group name");
-    }
-
-    @Test
-    @Ignore // TODO: fix and un-ignore
-    public void testQueryMessages() {
-        RcsMessageQueryParams queryParameters = new RcsMessageQueryParams.Builder().build();
-        Bundle bundle = new Bundle();
-        bundle.putParcelable(MESSAGE_QUERY_PARAMETERS_KEY, queryParameters);
-
-        Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/message"), null, bundle,
-                null);
-
-        assertThat(cursor.getCount()).isEqualTo(3);
-        cursor.moveToNext();
-        assertThat(cursor.getInt(cursor.getColumnIndex(MESSAGE_ID_COLUMN))).isEqualTo(3);
-        assertThat(cursor.getInt(cursor.getColumnIndex(RCS_THREAD_ID_COLUMN))).isEqualTo(3);
-
-        cursor.moveToNext();
-        assertThat(cursor.getInt(cursor.getColumnIndex(MESSAGE_ID_COLUMN))).isEqualTo(2);
-        assertThat(cursor.getInt(cursor.getColumnIndex(RCS_THREAD_ID_COLUMN))).isEqualTo(1);
-
-        cursor.moveToNext();
-        assertThat(cursor.getInt(cursor.getColumnIndex(MESSAGE_ID_COLUMN))).isEqualTo(1);
-        assertThat(cursor.getInt(cursor.getColumnIndex(RCS_THREAD_ID_COLUMN))).isEqualTo(1);
-    }
-
-    @Test
-    @Ignore // TODO: fix and un-ignore
-    public void testQueryMessagesWithContinuation() {
-        RcsMessageQueryParams queryParameters =
-                new RcsMessageQueryParams.Builder().setMessageLike("%o%message").setResultLimit(
-                        1).setSortProperty(RcsMessageQueryParams.SORT_BY_TIMESTAMP)
-                        .setSortDirection(true).build();
-        Bundle bundle = new Bundle();
-        bundle.putParcelable(MESSAGE_QUERY_PARAMETERS_KEY, queryParameters);
-
-        // Perform the initial query
-        Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/message"), null, bundle,
-                null);
-
-        assertThat(cursor.getCount()).isEqualTo(1);
-        cursor.moveToNext();
-        assertThat(cursor.getInt(cursor.getColumnIndex(MESSAGE_ID_COLUMN))).isEqualTo(3);
-        assertThat(cursor.getInt(cursor.getColumnIndex(RCS_THREAD_ID_COLUMN))).isEqualTo(3);
-        assertThat(cursor.getInt(cursor.getColumnIndex(ORIGINATION_TIMESTAMP_COLUMN))).isEqualTo(
-                200);
-        assertThat(cursor.getString(cursor.getColumnIndex(MESSAGE_TYPE_COLUMN))).isEqualTo(
-                "Group message");
-
-        // Perform the continuation query
-        RcsQueryContinuationToken continuationToken = cursor.getExtras().getParcelable(
-                QUERY_CONTINUATION_TOKEN);
-        assertThat(continuationToken).isNotNull();
-        bundle.clear();
-        bundle.putParcelable(QUERY_CONTINUATION_TOKEN, continuationToken);
-
-        cursor = mContentResolver.query(Uri.parse("content://rcs/message"), null, bundle, null);
-
-        assertThat(cursor.getCount()).isEqualTo(1);
-        cursor.moveToNext();
-        assertThat(cursor.getInt(cursor.getColumnIndex(MESSAGE_ID_COLUMN))).isEqualTo(1);
-        assertThat(cursor.getInt(cursor.getColumnIndex(RCS_THREAD_ID_COLUMN))).isEqualTo(1);
-        assertThat(cursor.getInt(cursor.getColumnIndex(ORIGINATION_TIMESTAMP_COLUMN))).isEqualTo(
-                300);
-        assertThat(cursor.getString(cursor.getColumnIndex(MESSAGE_TEXT_COLUMN))).isEqualTo(
-                "Old message");
-    }
-
-    @Test
-    @Ignore // TODO: fix and un-ignore
-    public void testQueryMessagesWithThreadFilter() {
-        RcsMessageQueryParams queryParameters =
-                new RcsMessageQueryParams.Builder().setThread(new RcsGroupThread(null, 3))
-                        .build();
-        Bundle bundle = new Bundle();
-        bundle.putParcelable(MESSAGE_QUERY_PARAMETERS_KEY, queryParameters);
-
-        // Perform the initial query
-        Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/message"), null, bundle,
-                null);
-
-        assertThat(cursor.getCount()).isEqualTo(1);
-        cursor.moveToNext();
-        assertThat(cursor.getInt(cursor.getColumnIndex(MESSAGE_ID_COLUMN))).isEqualTo(3);
-        assertThat(cursor.getInt(cursor.getColumnIndex(RCS_THREAD_ID_COLUMN))).isEqualTo(3);
-        assertThat(cursor.getInt(cursor.getColumnIndex(ORIGINATION_TIMESTAMP_COLUMN))).isEqualTo(
-                200);
-        assertThat(cursor.getString(cursor.getColumnIndex(MESSAGE_TEXT_COLUMN))).isEqualTo(
-                "Group message");
-
-    }
-
-    @Test
-    public void testQueryParticipantOf1To1Thread() {
-        // query the participant back
-        Uri queryUri = Uri.parse("content://rcs/p2p_thread/1/participant");
-        Cursor cursor = mContentResolver.query(queryUri, null, null, null, null);
-        assertThat(cursor.getCount()).isEqualTo(1);
-        cursor.moveToNext();
-
-        assertThat(cursor.getInt(1)).isEqualTo(99);
-        assertThat(cursor.getString(2)).isEqualTo("Some alias");
-    }
-
-    @Test
-    public void testQueryParticipantOfGroupThread() {
-        // query all the participants in this thread
-        Uri queryUri = Uri.parse("content://rcs/group_thread/3/participant");
-        Cursor cursor = mContentResolver.query(queryUri, null, null, null, null);
-        assertThat(cursor.getCount()).isEqualTo(1);
-        cursor.moveToNext();
-
-        assertThat(cursor.getInt(cursor.getColumnIndex(RCS_PARTICIPANT_ID_COLUMN))).isEqualTo(1);
-        assertThat(cursor.getInt(cursor.getColumnIndex(CANONICAL_ADDRESS_ID_COLUMN))).isEqualTo(99);
-        assertThat(cursor.getString(cursor.getColumnIndex(RCS_ALIAS_COLUMN))).isEqualTo(
-                "Some alias");
-    }
-
-    @Test
-    public void testQueryParticipantOfGroupThreadWithId() {
-        Cursor cursor = mContentResolver.query(
-                Uri.parse("content://rcs/group_thread/3/participant/1"), null, null, null, null);
-        assertThat(cursor.getCount()).isEqualTo(1);
-        cursor.moveToNext();
-
-        assertThat(cursor.getInt(cursor.getColumnIndex(RCS_PARTICIPANT_ID_COLUMN))).isEqualTo(1);
-        assertThat(cursor.getInt(cursor.getColumnIndex(CANONICAL_ADDRESS_ID_COLUMN))).isEqualTo(99);
-        assertThat(cursor.getString(cursor.getColumnIndex(RCS_ALIAS_COLUMN))).isEqualTo(
-                "Some alias");
-    }
-
-    @Test
-    public void testQueryFileTransfer() {
-        ContentValues values = new ContentValues();
-        // add an incoming message to the thread 2
-        assertThat(mContentResolver.insert(Uri.parse("content://rcs/p2p_thread/2/incoming_message"),
-                values)).isEqualTo(Uri.parse("content://rcs/p2p_thread/2/incoming_message/4"));
-
-        // add a file transfer
-        values.put(SESSION_ID_COLUMN, "session_id");
-        values.put(FILE_SIZE_COLUMN, 1234567890);
-        assertThat(
-                mContentResolver.insert(Uri.parse("content://rcs/message/4/file_transfer"),
-                        values)).isEqualTo(Uri.parse("content://rcs/file_transfer/1"));
-
-        // query the file transfer back
-        Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/file_transfer/1"), null,
-                null, null, null, null);
-        assertThat(cursor.getCount()).isEqualTo(1);
-
-        cursor.moveToNext();
-        assertThat(cursor.getInt(0)).isEqualTo(1);
-        assertThat(cursor.getInt(1)).isEqualTo(4);
-        assertThat(cursor.getString(2)).isEqualTo("session_id");
-        assertThat(cursor.getLong(5)).isEqualTo(1234567890);
-    }
-}
diff --git a/tests/src/com/android/providers/telephony/RcsProviderTestable.java b/tests/src/com/android/providers/telephony/RcsProviderTestable.java
deleted file mode 100644
index 569fcdb..0000000
--- a/tests/src/com/android/providers/telephony/RcsProviderTestable.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * 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.Context;
-import android.content.pm.PackageManager;
-import android.content.pm.ProviderInfo;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.telephony.TelephonyManager;
-import android.test.mock.MockContentResolver;
-import android.test.mock.MockContext;
-
-import org.mockito.Mockito;
-
-/**
- * A subclass of RcsProvider used for testing on an in-memory database
- */
-public class RcsProviderTestable extends RcsProvider {
-    private MockContextWithProvider mockContextWithProvider;
-
-    @Override
-    public boolean onCreate() {
-        mockContextWithProvider = new MockContextWithProvider(this);
-        mDbOpenHelper = new InMemoryRcsDatabase();
-        mParticipantHelper = new RcsProviderParticipantHelper(mDbOpenHelper);
-        mThreadHelper = new RcsProviderThreadHelper(mDbOpenHelper);
-        mMessageHelper = new RcsProviderMessageHelper(mDbOpenHelper);
-        mEventHelper = new RcsProviderEventHelper(mDbOpenHelper);
-        return true;
-    }
-
-    protected void tearDown() {
-        mDbOpenHelper.close();
-    }
-
-    public SQLiteDatabase getWritableDatabase() {
-        return mDbOpenHelper.getWritableDatabase();
-    }
-
-    class InMemoryRcsDatabase extends SQLiteOpenHelper {
-        InMemoryRcsDatabase() {
-            super(null,        // no context is needed for in-memory db
-                    null,      // db file name is null for in-memory db
-                    null,      // CursorFactory is null by default
-                    1);        // db version is no-op for tests
-        }
-
-        @Override
-        public void onCreate(SQLiteDatabase db) {
-            MmsSmsDatabaseHelper mmsSmsDatabaseHelper = new MmsSmsDatabaseHelper(
-                mockContextWithProvider, null);
-            mmsSmsDatabaseHelper.createMmsTables(db);
-            mmsSmsDatabaseHelper.createSmsTables(db);
-            mmsSmsDatabaseHelper.createCommonTables(db);
-
-            RcsProviderThreadHelper.createThreadTables(db);
-            RcsProviderParticipantHelper.createParticipantTables(db);
-            RcsProviderMessageHelper.createRcsMessageTables(db);
-            RcsProviderEventHelper.createRcsEventTables(db);
-        }
-
-        @Override
-        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
-            // no-op
-        }
-    }
-
-    static class MockContextWithProvider extends MockContext {
-        private final MockContentResolver mResolver;
-
-        MockContextWithProvider(RcsProvider rcsProvider) {
-            mResolver = new MockContentResolver();
-
-            // Add authority="rcs" to given smsProvider
-            ProviderInfo providerInfo = new ProviderInfo();
-            providerInfo.authority = RcsProvider.AUTHORITY;
-            rcsProvider.attachInfoForTesting(this, providerInfo);
-            mResolver.addProvider(RcsProvider.AUTHORITY, rcsProvider);
-        }
-
-        @Override
-        public MockContentResolver getContentResolver() {
-            return mResolver;
-        }
-
-        @Override
-        public PackageManager getPackageManager() {
-            return Mockito.mock(PackageManager.class);
-        }
-
-        @Override
-        public Object getSystemService(String name) {
-            switch (name) {
-                case Context.APP_OPS_SERVICE:
-                    return Mockito.mock(AppOpsManager.class);
-                case Context.TELEPHONY_SERVICE:
-                    return Mockito.mock(TelephonyManager.class);
-                default:
-                    return null;
-            }
-        }
-
-        @Override
-        public boolean isCredentialProtectedStorage() {
-            return false;
-        }
-    }
-}
diff --git a/tests/src/com/android/providers/telephony/RcsProviderUpdateTest.java b/tests/src/com/android/providers/telephony/RcsProviderUpdateTest.java
deleted file mode 100644
index 4ba7c1c..0000000
--- a/tests/src/com/android/providers/telephony/RcsProviderUpdateTest.java
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- * 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 static android.provider.Telephony.RcsColumns.Rcs1To1ThreadColumns.FALLBACK_THREAD_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.HEIGHT_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.WIDTH_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsGroupThreadColumns.GROUP_NAME_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsGroupThreadColumns.OWNER_PARTICIPANT_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsIncomingMessageColumns.ARRIVAL_TIMESTAMP_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageColumns.ORIGINATION_TIMESTAMP_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsMessageDeliveryColumns.DELIVERED_TIMESTAMP_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.CANONICAL_ADDRESS_ID_COLUMN;
-import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.RCS_ALIAS_COLUMN;
-
-import static com.android.providers.telephony.RcsProviderHelper.setup1To1Thread;
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.net.Uri;
-import android.provider.Telephony.RcsColumns.RcsMessageDeliveryColumns;
-import android.test.mock.MockContentResolver;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
-
-@RunWith(AndroidJUnit4.class)
-public class RcsProviderUpdateTest {
-    private MockContentResolver mContentResolver;
-    private RcsProviderTestable mRcsProvider;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mRcsProvider = new RcsProviderTestable();
-        RcsProviderTestable.MockContextWithProvider
-                context = new RcsProviderTestable.MockContextWithProvider(mRcsProvider);
-        mContentResolver = context.getContentResolver();
-
-        // insert a participant
-        //  first into the MmsSmsProvider
-        mRcsProvider.getWritableDatabase().execSQL(
-                "INSERT INTO canonical_addresses VALUES (1, \"+15551234567\")");
-
-        //  then into the RcsProvider
-        ContentValues participantValues = new ContentValues();
-        participantValues.put(RCS_ALIAS_COLUMN, "Bob");
-        participantValues.put(CANONICAL_ADDRESS_ID_COLUMN, 1);
-        assertThat(mContentResolver.insert(Uri.parse("content://rcs/participant"),
-                participantValues)).isEqualTo(Uri.parse("content://rcs/participant/1"));
-
-        // insert fallback threads
-        mRcsProvider.getWritableDatabase().execSQL("INSERT INTO threads(_id) VALUES (1)");
-        mRcsProvider.getWritableDatabase().execSQL("INSERT INTO threads(_id) VALUES (2)");
-
-        setup1To1Thread(mContentResolver);
-
-        // insert one group thread
-        ContentValues groupContentValues = new ContentValues();
-        groupContentValues.put(OWNER_PARTICIPANT_COLUMN, 1);
-        groupContentValues.put(GROUP_NAME_COLUMN, "Name");
-        Uri groupThreadUri = Uri.parse("content://rcs/group_thread");
-        assertThat(mContentResolver.insert(groupThreadUri, groupContentValues)).isEqualTo(
-                Uri.parse("content://rcs/group_thread/2"));
-
-        Uri groupInsertionUri = Uri.parse("content://rcs/group_thread/2/participant/1");
-        assertThat(mContentResolver.insert(groupInsertionUri, null)).isEqualTo(groupInsertionUri);
-
-        // add incoming and outgoing messages to both threads
-        ContentValues messageValues = new ContentValues();
-        assertThat(mContentResolver.insert(Uri.parse("content://rcs/p2p_thread/1/incoming_message"),
-                messageValues)).isEqualTo(
-                Uri.parse("content://rcs/p2p_thread/1/incoming_message/1"));
-        assertThat(mContentResolver.insert(Uri.parse("content://rcs/p2p_thread/1/outgoing_message"),
-                messageValues)).isEqualTo(
-                Uri.parse("content://rcs/p2p_thread/1/outgoing_message/2"));
-        assertThat(
-                mContentResolver.insert(Uri.parse("content://rcs/group_thread/2/incoming_message"),
-                        messageValues)).isEqualTo(
-                Uri.parse("content://rcs/group_thread/2/incoming_message/3"));
-        assertThat(
-                mContentResolver.insert(Uri.parse("content://rcs/group_thread/2/outgoing_message"),
-                        messageValues)).isEqualTo(
-                Uri.parse("content://rcs/group_thread/2/outgoing_message/4"));
-
-        // add message delivery to the outgoing messages
-        ContentValues deliveryValues = new ContentValues();
-        assertThat(mContentResolver.insert(Uri.parse("content://rcs/outgoing_message/2/delivery/1"),
-                deliveryValues)).isEqualTo(
-                Uri.parse("content://rcs/outgoing_message/2/delivery/1"));
-        assertThat(mContentResolver.insert(Uri.parse("content://rcs/outgoing_message/4/delivery/1"),
-                deliveryValues)).isEqualTo(
-                Uri.parse("content://rcs/outgoing_message/4/delivery/1"));
-
-        // add a file transfer to an incoming message
-        ContentValues fileTransferValues = new ContentValues();
-        assertThat(mContentResolver.insert(Uri.parse("content://rcs/message/3/file_transfer"),
-                fileTransferValues)).isEqualTo(Uri.parse("content://rcs/file_transfer/1"));
-    }
-
-    @After
-    public void tearDown() {
-        mRcsProvider.tearDown();
-    }
-
-    @Test
-    public void testUpdate1To1ThreadWithSelection() {
-        // update the fallback thread id
-        ContentValues contentValues = new ContentValues(1);
-        contentValues.put(FALLBACK_THREAD_ID_COLUMN, 2);
-        Uri p2pThreadUri = Uri.parse("content://rcs/p2p_thread");
-
-        assertThat(mContentResolver.update(p2pThreadUri, contentValues, "rcs_fallback_thread_id=1",
-                null)).isEqualTo(1);
-
-        // verify the thread is actually updated
-        Cursor cursor = mContentResolver.query(p2pThreadUri,
-                new String[]{FALLBACK_THREAD_ID_COLUMN}, "rcs_fallback_thread_id=2", null, null);
-        assertThat(cursor.getCount()).isEqualTo(1);
-
-        cursor.moveToNext();
-        assertThat(cursor.getInt(0)).isEqualTo(2);
-    }
-
-    @Test
-    public void testUpdate1To1ThreadWithId() {
-        // update the fallback thread id
-        ContentValues contentValues = new ContentValues(1);
-        contentValues.put(FALLBACK_THREAD_ID_COLUMN, 2);
-        Uri p2pThreadUri = Uri.parse("content://rcs/p2p_thread/1");
-        assertThat(mContentResolver.update(p2pThreadUri, contentValues, null, null)).isEqualTo(1);
-
-        // verify the thread is actually updated
-        Cursor cursor = mContentResolver.query(p2pThreadUri,
-                new String[]{FALLBACK_THREAD_ID_COLUMN}, null, null, null);
-        assertThat(cursor.getCount()).isEqualTo(1);
-
-        cursor.moveToNext();
-        assertThat(cursor.getInt(0)).isEqualTo(2);
-    }
-
-    @Test
-    public void testUpdateGroupThreadWithSelection() {
-        // update the group name
-        ContentValues contentValues = new ContentValues(1);
-        contentValues.put(GROUP_NAME_COLUMN, "New name");
-        Uri groupThreadUri = Uri.parse("content://rcs/group_thread");
-        assertThat(mContentResolver.update(groupThreadUri, contentValues, "group_name=\"Name\"",
-                null)).isEqualTo(1);
-
-        // verify the thread is actually updated
-        Cursor cursor = mContentResolver.query(groupThreadUri, new String[]{GROUP_NAME_COLUMN},
-                "group_name=\"New name\"", null, null);
-        assertThat(cursor.getCount()).isEqualTo(1);
-
-        cursor.moveToNext();
-        assertThat(cursor.getString(0)).isEqualTo("New name");
-    }
-
-    @Test
-    public void testUpdateGroupThreadWithId() {
-        // update the group name
-        ContentValues contentValues = new ContentValues(1);
-        contentValues.put(GROUP_NAME_COLUMN, "New name");
-        Uri groupThreadUri = Uri.parse("content://rcs/group_thread/2");
-        assertThat(mContentResolver.update(groupThreadUri, contentValues, null, null)).isEqualTo(1);
-
-        // verify the thread is actually updated
-        Cursor cursor = mContentResolver.query(groupThreadUri, new String[]{GROUP_NAME_COLUMN},
-                null, null, null);
-        assertThat(cursor.getCount()).isEqualTo(1);
-        cursor.moveToNext();
-        assertThat(cursor.getString(0)).isEqualTo("New name");
-    }
-
-    @Test
-    public void testUpdateParticipantWithId() {
-        // change the participant name from Bob to Bobby
-        ContentValues contentValues = new ContentValues(1);
-        contentValues.put(RCS_ALIAS_COLUMN, "Bobby");
-
-        Uri participantUri = Uri.parse("content://rcs/participant/1");
-
-        assertThat(mContentResolver.update(participantUri, contentValues, null, null)).isEqualTo(1);
-
-        // verify participant is actually updated
-        Cursor cursor = mContentResolver.query(participantUri, new String[]{RCS_ALIAS_COLUMN}, null,
-                null, null);
-        assertThat(cursor.getCount()).isEqualTo(1);
-        cursor.moveToNext();
-        assertThat(cursor.getString(0)).isEqualTo("Bobby");
-    }
-
-    @Test
-    public void testUpdate1To1ThreadParticipantFails() {
-        assertThat(
-                mContentResolver.update(Uri.parse("content://rcs/p2p_thread/1/participant/1"), null,
-                        null, null)).isEqualTo(0);
-    }
-
-    @Test
-    public void testUpdateGroupParticipantFails() {
-        assertThat(mContentResolver.update(Uri.parse("content://rcs/group_thread/2/participant/1"),
-                null, null, null)).isEqualTo(0);
-    }
-
-    @Test
-    public void testUpdateUnifiedMessageViewFails() {
-        ContentValues updateValues = new ContentValues();
-        updateValues.put(ORIGINATION_TIMESTAMP_COLUMN, 1234567890);
-
-        assertThat(mContentResolver.update(Uri.parse("content://rcs/message"), updateValues, null,
-                null)).isEqualTo(0);
-        assertThat(mContentResolver.update(Uri.parse("content://rcs/message/1"), updateValues, null,
-                null)).isEqualTo(0);
-    }
-
-    @Test
-    public void testUpdateMessageOnThreadFails() {
-        ContentValues updateValues = new ContentValues();
-        updateValues.put(ORIGINATION_TIMESTAMP_COLUMN, 1234567890);
-
-        assertThat(mContentResolver.update(Uri.parse("content://rcs/p2p_thread/1/incoming_message"),
-                updateValues, null, null)).isEqualTo(0);
-        assertThat(
-                mContentResolver.update(Uri.parse("content://rcs/p2p_thread/1/incoming_message/1"),
-                        updateValues, null, null)).isEqualTo(0);
-        assertThat(
-                mContentResolver.update(Uri.parse("content://rcs/group_thread/2/outgoing_message"),
-                        updateValues, null, null)).isEqualTo(0);
-        assertThat(mContentResolver.update(
-                Uri.parse("content://rcs/groupp_thread/2/outgoing_message/1"), updateValues, null,
-                null)).isEqualTo(0);
-    }
-
-    @Test
-    public void testUpdateMessage() {
-        // update the message
-        ContentValues updateValues = new ContentValues(1);
-        updateValues.put(ORIGINATION_TIMESTAMP_COLUMN, 1234567890);
-        assertThat(
-                mContentResolver.update(Uri.parse("content://rcs/outgoing_message/2"), updateValues,
-                        null, null)).isEqualTo(1);
-
-        // verify the value is actually updated
-        Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/outgoing_message/2"), null,
-                null, null, null, null);
-        assertThat(cursor.getCount()).isEqualTo(1);
-        cursor.moveToNext();
-        assertThat(cursor.getLong(5)).isEqualTo(1234567890);
-        cursor.close();
-    }
-
-    @Test
-    @Ignore // TODO: fix and un-ignore
-    public void testUpdateIncomingMessageSpecificColumn() {
-        // update the message
-        ContentValues updateValues = new ContentValues(1);
-        updateValues.put(ARRIVAL_TIMESTAMP_COLUMN, 987654321);
-        assertThat(
-                mContentResolver.update(Uri.parse("content://rcs/incoming_message/3"), updateValues,
-                        null, null)).isEqualTo(1);
-
-        // verify the value is actually updated
-        Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/incoming_message/3"), null,
-                null, null, null, null);
-        assertThat(cursor.getCount()).isEqualTo(1);
-        cursor.moveToNext();
-        assertThat(cursor.getLong(7)).isEqualTo(987654321);
-        cursor.close();
-    }
-
-    @Test
-    public void testUpdateMessageDelivery() {
-        ContentValues updateValues = new ContentValues();
-        updateValues.put(DELIVERED_TIMESTAMP_COLUMN, 12345);
-        updateValues.put(RcsMessageDeliveryColumns.SEEN_TIMESTAMP_COLUMN, 54321);
-
-        assertThat(mContentResolver.update(Uri.parse("content://rcs/outgoing_message/2/delivery/1"),
-                updateValues, null, null)).isEqualTo(1);
-
-        // verify the value is actually updated
-        Cursor cursor = mContentResolver.query(
-                Uri.parse("content://rcs/outgoing_message/2/delivery"), null, null, null, null,
-                null);
-        assertThat(cursor.getCount()).isEqualTo(1);
-        cursor.moveToNext();
-        assertThat(cursor.getInt(0)).isEqualTo(2);
-        assertThat(cursor.getInt(1)).isEqualTo(1);
-        assertThat(cursor.getLong(2)).isEqualTo(12345);
-        assertThat(cursor.getLong(3)).isEqualTo(54321);
-    }
-
-    @Test
-    public void testUpdateFileTransfer() {
-        ContentValues updateValues = new ContentValues();
-        updateValues.put(WIDTH_COLUMN, 640);
-        updateValues.put(HEIGHT_COLUMN, 480);
-
-        assertThat(mContentResolver.update(Uri.parse("content://rcs/file_transfer/1"), updateValues,
-                null, null)).isEqualTo(1);
-
-        // verify that the values are actually updated
-        Cursor cursor = mContentResolver.query(Uri.parse("content://rcs/file_transfer/1"), null,
-                null, null, null, null);
-        assertThat(cursor.getCount()).isEqualTo(1);
-        cursor.moveToNext();
-        assertThat(cursor.getInt(8)).isEqualTo(640);
-        assertThat(cursor.getInt(9)).isEqualTo(480);
-    }
-}
diff --git a/tests/src/com/android/providers/telephony/ServiceStateProviderTest.java b/tests/src/com/android/providers/telephony/ServiceStateProviderTest.java
deleted file mode 100644
index b6f5508..0000000
--- a/tests/src/com/android/providers/telephony/ServiceStateProviderTest.java
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * Copyright (C) 2016 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 static android.provider.Telephony.ServiceStateTable;
-import static android.provider.Telephony.ServiceStateTable.getUriForSubscriptionId;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-
-import android.content.Context;
-import android.content.pm.ProviderInfo;
-import android.database.ContentObserver;
-import android.database.Cursor;
-import android.net.Uri;
-import android.telephony.ServiceState;
-import android.telephony.SubscriptionManager;
-import android.test.mock.MockContentResolver;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-
-/**
- * Tests for simple queries of ServiceStateProvider.
- *
- * Build, install and run the tests by running the commands below:
- *     runtest --path <dir or file>
- *     runtest --path <dir or file> --test-method <testMethodName>
- *     e.g.)
- *         runtest --path tests/src/com/android/providers/telephony/ServiceStateProviderTest.java \
- *                 --test-method testGetServiceState
- */
-public class ServiceStateProviderTest {
-    private static final String TAG = "ServiceStateProviderTest";
-
-    private Context mContext;
-    private MockContentResolver mContentResolver;
-    private ServiceState testServiceState;
-    private ServiceState testServiceStateForSubId1;
-
-    private final String[] testProjection =
-    {
-        ServiceStateTable.VOICE_REG_STATE,
-        ServiceStateTable.DATA_REG_STATE,
-        ServiceStateTable.VOICE_OPERATOR_ALPHA_LONG,
-        ServiceStateTable.VOICE_OPERATOR_ALPHA_SHORT,
-        ServiceStateTable.VOICE_OPERATOR_NUMERIC,
-        ServiceStateTable.DATA_OPERATOR_ALPHA_LONG,
-        ServiceStateTable.DATA_OPERATOR_ALPHA_SHORT,
-        ServiceStateTable.DATA_OPERATOR_NUMERIC,
-        ServiceStateTable.IS_MANUAL_NETWORK_SELECTION,
-        ServiceStateTable.RIL_VOICE_RADIO_TECHNOLOGY,
-        ServiceStateTable.RIL_DATA_RADIO_TECHNOLOGY,
-        ServiceStateTable.CSS_INDICATOR,
-        ServiceStateTable.NETWORK_ID,
-        ServiceStateTable.SYSTEM_ID,
-        ServiceStateTable.CDMA_ROAMING_INDICATOR,
-        ServiceStateTable.CDMA_DEFAULT_ROAMING_INDICATOR,
-        ServiceStateTable.CDMA_ERI_ICON_INDEX,
-        ServiceStateTable.CDMA_ERI_ICON_MODE,
-        ServiceStateTable.IS_EMERGENCY_ONLY,
-        ServiceStateTable.IS_USING_CARRIER_AGGREGATION,
-        ServiceStateTable.OPERATOR_ALPHA_LONG_RAW,
-        ServiceStateTable.OPERATOR_ALPHA_SHORT_RAW,
-    };
-
-    @Before
-    public void setUp() throws Exception {
-        mContext = mock(Context.class);
-        mContentResolver = new MockContentResolver() {
-            @Override
-            public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
-                throw new RuntimeException("notifyChange!");
-            }
-        };
-        doReturn(mContentResolver).when(mContext).getContentResolver();
-
-        testServiceState = new ServiceState();
-        testServiceState.setStateOutOfService();
-        testServiceStateForSubId1 = new ServiceState();
-        testServiceStateForSubId1.setStateOff();
-
-        // Mock out the actual phone state
-        ServiceStateProvider provider = new ServiceStateProvider() {
-            @Override
-            public ServiceState getServiceState(int subId) {
-                if (subId == 1) {
-                    return testServiceStateForSubId1;
-                } else {
-                    return testServiceState;
-                }
-            }
-
-            @Override
-            public int getDefaultSubId() {
-                return 0;
-            }
-        };
-        ProviderInfo providerInfo = new ProviderInfo();
-        providerInfo.authority = "service-state";
-        provider.attachInfoForTesting(mContext, providerInfo);
-        mContentResolver.addProvider("service-state", provider);
-    }
-
-    @Test
-    @SmallTest
-    public void testQueryServiceStateWithNoSubId() {
-        // Verify that when calling query with no subId in the uri the default ServiceState is
-        // returned.
-        // In this case the subId is set to 0 and the expected service state is
-        // testServiceState.
-        verifyServiceStateForSubId(ServiceStateTable.CONTENT_URI, testServiceState);
-    }
-
-    @Test
-    @SmallTest
-    public void testGetServiceStateWithDefaultSubId() {
-        // Verify that when calling with the DEFAULT_SUBSCRIPTION_ID the correct ServiceState is
-        // returned
-        // In this case the subId is set to 0 and the expected service state is
-        // testServiceState.
-        verifyServiceStateForSubId(
-                getUriForSubscriptionId(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID),
-                testServiceState);
-    }
-
-    /**
-     * Test querying the service state for a given subId
-     */
-    @Test
-    @SmallTest
-    public void testGetServiceStateForSubId() {
-        // Verify that when calling with a specific subId the correct ServiceState is returned
-        // In this case the subId is set to 1 and the expected service state is
-        // testServiceStateForSubId1
-        verifyServiceStateForSubId(getUriForSubscriptionId(1), testServiceStateForSubId1);
-    }
-
-    private void verifyServiceStateForSubId(Uri uri, ServiceState ss) {
-        Cursor cursor = mContentResolver.query(uri, testProjection, "",
-                null, null);
-        assertNotNull(cursor);
-        cursor.moveToFirst();
-
-        final int voiceRegState = ss.getVoiceRegState();
-        final int dataRegState = ss.getDataRegState();
-        final String voiceOperatorAlphaLong = ss.getVoiceOperatorAlphaLong();
-        final String voiceOperatorAlphaShort = ss.getVoiceOperatorAlphaShort();
-        final String voiceOperatorNumeric = ss.getVoiceOperatorNumeric();
-        final String dataOperatorAlphaLong = ss.getDataOperatorAlphaLong();
-        final String dataOperatorAlphaShort = ss.getDataOperatorAlphaShort();
-        final String dataOperatorNumeric = ss.getDataOperatorNumeric();
-        final int isManualNetworkSelection = (ss.getIsManualSelection()) ? 1 : 0;
-        final int rilVoiceRadioTechnology = ss.getRilVoiceRadioTechnology();
-        final int rilDataRadioTechnology = ss.getRilDataRadioTechnology();
-        final int cssIndicator = ss.getCssIndicator();
-        final int networkId = ss.getCdmaNetworkId();
-        final int systemId = ss.getCdmaSystemId();
-        final int cdmaRoamingIndicator = ss.getCdmaRoamingIndicator();
-        final int cdmaDefaultRoamingIndicator = ss.getCdmaDefaultRoamingIndicator();
-        final int cdmaEriIconIndex = ss.getCdmaEriIconIndex();
-        final int cdmaEriIconMode = ss.getCdmaEriIconMode();
-        final int isEmergencyOnly = (ss.isEmergencyOnly()) ? 1 : 0;
-        final int isUsingCarrierAggregation = (ss.isUsingCarrierAggregation()) ? 1 : 0;
-        final String operatorAlphaLongRaw = ss.getOperatorAlphaLongRaw();
-        final String operatorAlphaShortRaw = ss.getOperatorAlphaShortRaw();
-
-        assertEquals(voiceRegState, cursor.getInt(0));
-        assertEquals(dataRegState, cursor.getInt(1));
-        assertEquals(voiceOperatorAlphaLong, cursor.getString(2));
-        assertEquals(voiceOperatorAlphaShort, cursor.getString(3));
-        assertEquals(voiceOperatorNumeric, cursor.getString(4));
-        assertEquals(dataOperatorAlphaLong, cursor.getString(5));
-        assertEquals(dataOperatorAlphaShort, cursor.getString(6));
-        assertEquals(dataOperatorNumeric, cursor.getString(7));
-        assertEquals(isManualNetworkSelection, cursor.getInt(8));
-        assertEquals(rilVoiceRadioTechnology, cursor.getInt(9));
-        assertEquals(rilDataRadioTechnology, cursor.getInt(10));
-        assertEquals(cssIndicator, cursor.getInt(11));
-        assertEquals(networkId, cursor.getInt(12));
-        assertEquals(systemId, cursor.getInt(13));
-        assertEquals(cdmaRoamingIndicator, cursor.getInt(14));
-        assertEquals(cdmaDefaultRoamingIndicator, cursor.getInt(15));
-        assertEquals(cdmaEriIconIndex, cursor.getInt(16));
-        assertEquals(cdmaEriIconMode, cursor.getInt(17));
-        assertEquals(isEmergencyOnly, cursor.getInt(18));
-        assertEquals(isUsingCarrierAggregation, cursor.getInt(19));
-        assertEquals(operatorAlphaLongRaw, cursor.getString(20));
-        assertEquals(operatorAlphaShortRaw, cursor.getString(21));
-    }
-
-    /**
-     * Test that we don't notify for certain field changes. (e.g. we don't notify when the NetworkId
-     * or SystemId change) This is an intentional behavior change from the broadcast.
-     */
-    @Test
-    @SmallTest
-    public void testNoNotify() {
-        int subId = 0;
-
-        ServiceState oldSS = new ServiceState();
-        oldSS.setStateOutOfService();
-        oldSS.setCdmaSystemAndNetworkId(1, 1);
-
-        ServiceState newSS = new ServiceState();
-        newSS.setStateOutOfService();
-        newSS.setCdmaSystemAndNetworkId(0, 0);
-
-        // Test that notifyChange is not called for these fields
-        boolean notifyChangeWasCalled = false;
-        try {
-            ServiceStateProvider.notifyChangeForSubIdAndField(mContext, oldSS, newSS, subId);
-        } catch (RuntimeException e) {
-            final String message = e.getMessage();
-            if (message != null &&  message.equals("notifyChange!")) {
-                notifyChangeWasCalled = true;
-            }
-        }
-        assertFalse(notifyChangeWasCalled);
-    }
-
-    @Test
-    @SmallTest
-    public void testNotifyChanged() {
-        int subId = 0;
-
-        ServiceState oldSS = new ServiceState();
-        oldSS.setStateOutOfService();
-        oldSS.setVoiceRegState(ServiceState.STATE_OUT_OF_SERVICE);
-
-        ServiceState copyOfOldSS = new ServiceState();
-        copyOfOldSS.setStateOutOfService();
-        copyOfOldSS.setVoiceRegState(ServiceState.STATE_OUT_OF_SERVICE);
-
-        ServiceState newSS = new ServiceState();
-        newSS.setStateOutOfService();
-        newSS.setVoiceRegState(ServiceState.STATE_POWER_OFF);
-
-        // Test that notifyChange is not called with no change in notifyChangeForSubIdAndField
-        boolean notifyChangeWasCalled = false;
-        try {
-            ServiceStateProvider.notifyChangeForSubIdAndField(mContext, oldSS, copyOfOldSS, subId);
-        } catch (RuntimeException e) {
-            final String message = e.getMessage();
-            if (message != null &&  message.equals("notifyChange!")) {
-                notifyChangeWasCalled = true;
-            }
-        }
-        assertFalse(notifyChangeWasCalled);
-
-        // Test that notifyChange is not called with no change in notifyChangeForSubId
-        notifyChangeWasCalled = false;
-        try {
-            ServiceStateProvider.notifyChangeForSubId(mContext, oldSS, copyOfOldSS, subId);
-        } catch (RuntimeException e) {
-            final String message = e.getMessage();
-            if (message != null &&  message.equals("notifyChange!")) {
-                notifyChangeWasCalled = true;
-            }
-        }
-        assertFalse(notifyChangeWasCalled);
-
-        // Test that notifyChange is called by notifyChangeForSubIdAndField when the voice_reg_state
-        // changes
-        notifyChangeWasCalled = false;
-        try {
-            ServiceStateProvider.notifyChangeForSubIdAndField(mContext, oldSS, newSS, subId);
-        } catch (RuntimeException e) {
-            final String message = e.getMessage();
-            if (message != null &&  message.equals("notifyChange!")) {
-                notifyChangeWasCalled = true;
-            }
-        }
-        assertTrue(notifyChangeWasCalled);
-
-        // Test that notifyChange is called by notifyChangeForSubId when the voice_reg_state changes
-        notifyChangeWasCalled = false;
-        try {
-            ServiceStateProvider.notifyChangeForSubId(mContext, oldSS, newSS, subId);
-        } catch (RuntimeException e) {
-            final String message = e.getMessage();
-            if (message != null &&  message.equals("notifyChange!")) {
-                notifyChangeWasCalled = true;
-            }
-        }
-        assertTrue(notifyChangeWasCalled);
-    }
-}
diff --git a/tests/src/com/android/providers/telephony/TelephonyBackupAgentTest.java b/tests/src/com/android/providers/telephony/TelephonyBackupAgentTest.java
index 37cf6e3..b1cd5e4 100644
--- a/tests/src/com/android/providers/telephony/TelephonyBackupAgentTest.java
+++ b/tests/src/com/android/providers/telephony/TelephonyBackupAgentTest.java
@@ -16,7 +16,10 @@
 
 package com.android.providers.telephony;
 
+import static org.junit.Assert.assertArrayEquals;
+
 import android.annotation.TargetApi;
+import android.app.backup.BackupDataOutput;
 import android.app.backup.FullBackupDataOutput;
 import android.content.ContentProvider;
 import android.content.ContentResolver;
@@ -26,6 +29,7 @@
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Build;
+import android.os.ParcelFileDescriptor;
 import android.provider.BaseColumns;
 import android.provider.Telephony;
 import android.test.AndroidTestCase;
@@ -40,22 +44,29 @@
 import android.util.Log;
 import android.util.SparseArray;
 
+import libcore.io.IoUtils;
+
 import com.google.android.mms.pdu.CharacterSets;
 
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
 
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
 import java.io.StringReader;
 import java.io.StringWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Tests for testing backup/restore of SMS and text MMS messages.
@@ -684,6 +695,44 @@
         assertEquals(backupSizeAfterSecondQuotaHit, fullBackupDataOutput.getSize());
     }
 
+    /**
+     * Test backups are consistent between runs. This ensures that when no data
+     * has changed between backup runs we don't generate a diff which needs to
+     * be sent to the server.
+     * @throws Exception
+     */
+    public void testBackup_WithoutChanges_DoesNotChangeOutput() throws Exception {
+        mSmsTable.addAll(Arrays.asList(mSmsRows));
+        mMmsTable.addAll(Arrays.asList(mMmsRows));
+
+        byte[] firstBackup = getBackup("1");
+        // Ensure there is some time between backup runs. This is the way to identify
+        // time dependent backup contents.
+        Thread.sleep(TimeUnit.MILLISECONDS.convert(1, TimeUnit.SECONDS));
+        byte[] secondBackup = getBackup("2");
+
+        // Make sure something has been backed up.
+        assertFalse(firstBackup == null || firstBackup.length == 0);
+
+        // Make sure the two backups are the same.
+        assertArrayEquals(firstBackup, secondBackup);
+    }
+
+    private byte[] getBackup(String runId) throws IOException {
+        File cacheDir = getContext().getCacheDir();
+        File backupOutput = File.createTempFile("backup", runId, cacheDir);
+        ParcelFileDescriptor outputFd =
+                ParcelFileDescriptor.open(backupOutput, ParcelFileDescriptor.MODE_WRITE_ONLY);
+        try {
+            FullBackupDataOutput fullBackupDataOutput = new FullBackupDataOutput(outputFd);
+            mTelephonyBackupAgent.onFullBackup(fullBackupDataOutput);
+            return IoUtils.readFileAsByteArray(backupOutput.getAbsolutePath());
+        } finally {
+            outputFd.close();
+            backupOutput.delete();
+        }
+    }
+
     // Adding random keys to JSON to test handling it by the BackupAgent on restore.
     private String addRandomDataToJson(String jsonString) throws JSONException {
         JSONArray jsonArray = new JSONArray(jsonString);
diff --git a/tests/src/com/android/providers/telephony/TelephonyDatabaseHelperTest.java b/tests/src/com/android/providers/telephony/TelephonyDatabaseHelperTest.java
index 8287352..0666169 100644
--- a/tests/src/com/android/providers/telephony/TelephonyDatabaseHelperTest.java
+++ b/tests/src/com/android/providers/telephony/TelephonyDatabaseHelperTest.java
@@ -25,6 +25,7 @@
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteOpenHelper;
+import android.provider.Telephony;
 import android.telephony.SubscriptionManager;
 import android.text.TextUtils;
 import android.util.Log;
@@ -59,7 +60,7 @@
     public void setUp() {
         Log.d(TAG, "setUp() +");
         mContext = InstrumentationRegistry.getContext();
-        mHelper = new TelephonyProvider.DatabaseHelper(mContext);
+        mHelper = new TelephonyProviderTestable().new DatabaseHelper(mContext);
         mInMemoryDbHelper = new InMemoryTelephonyProviderV5DbHelper();
         Log.d(TAG, "setUp() -");
     }
@@ -69,7 +70,7 @@
         Log.d(TAG, "databaseHelperOnUpgrade_hasApnSetIdField");
         // (5 << 16 | 6) is the first upgrade trigger in onUpgrade
         SQLiteDatabase db = mInMemoryDbHelper.getWritableDatabase();
-        mHelper.onUpgrade(db, (4 << 16), TelephonyProvider.DatabaseHelper.getVersion(mContext));
+        mHelper.onUpgrade(db, (4 << 16), TelephonyProvider.getVersion(mContext));
 
         // the upgraded db must have the APN_SET_ID field
         Cursor cursor = db.query("carriers", null, null, null, null, null, null);
@@ -84,7 +85,7 @@
         Log.d(TAG, "databaseHelperOnUpgrade_hasSubscriptionTypeField");
         // (5 << 16 | 6) is the first upgrade trigger in onUpgrade
         SQLiteDatabase db = mInMemoryDbHelper.getWritableDatabase();
-        mHelper.onUpgrade(db, (4 << 16), TelephonyProvider.DatabaseHelper.getVersion(mContext));
+        mHelper.onUpgrade(db, (4 << 16), TelephonyProvider.getVersion(mContext));
 
         // the upgraded db must have the Telephony.Carriers.CARRIER_ID field
         Cursor cursor = db.query("carriers", null, null, null, null, null, null);
@@ -97,7 +98,7 @@
     public void databaseHelperOnUpgrade_hasCountryIsoField() {
         Log.d(TAG, "databaseHelperOnUpgrade_hasCountryIsoField");
         SQLiteDatabase db = mInMemoryDbHelper.getWritableDatabase();
-        mHelper.onUpgrade(db, (4 << 16), TelephonyProvider.DatabaseHelper.getVersion(mContext));
+        mHelper.onUpgrade(db, (4 << 16), TelephonyProvider.getVersion(mContext));
 
         // the upgraded db must have the Telephony.Carriers.CARRIER_ID field
         Cursor cursor = db.query("simInfo", null, null, null, null, null, null);
@@ -110,7 +111,7 @@
     public void databaseHelperOnUpgrade_hasProfileClassField() {
         Log.d(TAG, "databaseHelperOnUpgrade_hasProfileClassField");
         SQLiteDatabase db = mInMemoryDbHelper.getWritableDatabase();
-        mHelper.onUpgrade(db, (4 << 16), TelephonyProvider.DatabaseHelper.getVersion(mContext));
+        mHelper.onUpgrade(db, (4 << 16), TelephonyProvider.getVersion(mContext));
 
         // the upgraded db must have the PROFILE_CLASS field
         Cursor cursor = db.query("siminfo", null, null, null, null, null, null);
@@ -124,7 +125,7 @@
         Log.d(TAG, "databaseHelperOnUpgrade_hasSkip464XlatField");
         // (5 << 16 | 6) is the first upgrade trigger in onUpgrade
         SQLiteDatabase db = mInMemoryDbHelper.getWritableDatabase();
-        mHelper.onUpgrade(db, (4 << 16), TelephonyProvider.DatabaseHelper.getVersion(mContext));
+        mHelper.onUpgrade(db, (4 << 16), TelephonyProvider.getVersion(mContext));
 
         // the upgraded db must have the Telephony.Carriers.CARRIER_ID field
         Cursor cursor = db.query("carriers", null, null, null, null, null, null);
@@ -138,7 +139,7 @@
         Log.d(TAG, "databaseHelperOnUpgrade_columnsMatchNewlyCreatedDb");
         // (5 << 16 | 6) is the first upgrade trigger in onUpgrade
         SQLiteDatabase db = mInMemoryDbHelper.getWritableDatabase();
-        mHelper.onUpgrade(db, (4 << 16), TelephonyProvider.DatabaseHelper.getVersion(mContext));
+        mHelper.onUpgrade(db, (4 << 16), TelephonyProvider.getVersion(mContext));
 
         // compare upgraded carriers table to a carriers table created from scratch
         db.execSQL(TelephonyProvider.getStringForCarrierTableCreation("carriers_full"));
@@ -174,7 +175,7 @@
         Log.d(TAG, "databaseHelperOnUpgrade_hasSubscriptionTypeField");
         // (5 << 16 | 6) is the first upgrade trigger in onUpgrade
         SQLiteDatabase db = mInMemoryDbHelper.getWritableDatabase();
-        mHelper.onUpgrade(db, (4 << 16), TelephonyProvider.DatabaseHelper.getVersion(mContext));
+        mHelper.onUpgrade(db, (4 << 16), TelephonyProvider.getVersion(mContext));
 
         // the upgraded db must have the SubscriptionManager.SUBSCRIPTION_TYPE field
         Cursor cursor = db.query("siminfo", null, null, null, null, null, null);
@@ -184,6 +185,22 @@
         assertTrue(Arrays.asList(upgradedColumns).contains(SubscriptionManager.SUBSCRIPTION_TYPE));
     }
 
+    @Test
+    public void databaseHelperOnUpgrade_hasImsRcsUceEnabledField() {
+        Log.d(TAG, "databaseHelperOnUpgrade_hasImsRcsUceEnabledField");
+        // (5 << 16 | 6) is the first upgrade trigger in onUpgrade
+        SQLiteDatabase db = mInMemoryDbHelper.getWritableDatabase();
+        mHelper.onUpgrade(db, (4 << 16), TelephonyProvider.getVersion(mContext));
+
+        // the upgraded db must have the SubscriptionManager.SUBSCRIPTION_TYPE field
+        Cursor cursor = db.query("siminfo", null, null, null, null, null, null);
+        String[] upgradedColumns = cursor.getColumnNames();
+        Log.d(TAG, "siminfo columns: " + Arrays.toString(upgradedColumns));
+
+        assertTrue(Arrays.asList(upgradedColumns).contains(
+                Telephony.SimInfo.COLUMN_IMS_RCS_UCE_ENABLED));
+    }
+
     /**
      * Helper for an in memory DB used to test the TelephonyProvider#DatabaseHelper.
      *
@@ -242,22 +259,22 @@
             Log.d(TAG, "InMemoryTelephonyProviderV5DbHelper onCreate creating the siminfo table");
             db.execSQL(
                     "CREATE TABLE siminfo ("
-                    + SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID
+                    + Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID
                     + " INTEGER PRIMARY KEY AUTOINCREMENT,"
-                    + SubscriptionManager.ICC_ID + " TEXT NOT NULL,"
-                    + SubscriptionManager.SIM_SLOT_INDEX
-                        + " INTEGER DEFAULT " + SubscriptionManager.SIM_NOT_INSERTED + ","
-                    + SubscriptionManager.DISPLAY_NAME + " TEXT,"
-                    + SubscriptionManager.NAME_SOURCE
-                        + " INTEGER DEFAULT " + SubscriptionManager.NAME_SOURCE_DEFAULT_SOURCE + ","
-                    + SubscriptionManager.COLOR
-                        + " INTEGER DEFAULT " + SubscriptionManager.COLOR_DEFAULT + ","
-                    + SubscriptionManager.NUMBER + " TEXT,"
-                    + SubscriptionManager.DISPLAY_NUMBER_FORMAT + " INTEGER NOT NULL"
-                        + " DEFAULT " + SubscriptionManager.DISPLAY_NUMBER_DEFAULT + ","
-                    + SubscriptionManager.DATA_ROAMING
-                        + " INTEGER DEFAULT " + SubscriptionManager.DATA_ROAMING_DEFAULT + ","
-                    + SubscriptionManager.CARD_ID + " TEXT NOT NULL"
+                    + Telephony.SimInfo.COLUMN_ICC_ID + " TEXT NOT NULL,"
+                    + Telephony.SimInfo.COLUMN_SIM_SLOT_INDEX
+                        + " INTEGER DEFAULT " + Telephony.SimInfo.SIM_NOT_INSERTED + ","
+                    + Telephony.SimInfo.COLUMN_DISPLAY_NAME + " TEXT,"
+                    + Telephony.SimInfo.COLUMN_NAME_SOURCE
+                        + " INTEGER DEFAULT " + Telephony.SimInfo.NAME_SOURCE_CARRIER_ID + ","
+                    + Telephony.SimInfo.COLUMN_COLOR
+                        + " INTEGER DEFAULT " + Telephony.SimInfo.COLOR_DEFAULT + ","
+                    + Telephony.SimInfo.COLUMN_NUMBER + " TEXT,"
+                    + Telephony.SimInfo.COLUMN_DISPLAY_NUMBER_FORMAT + " INTEGER NOT NULL"
+                        + " DEFAULT " + Telephony.SimInfo.DISPLAY_NUMBER_DEFAULT + ","
+                    + Telephony.SimInfo.COLUMN_DATA_ROAMING
+                        + " INTEGER DEFAULT " + Telephony.SimInfo.DATA_ROAMING_DISABLE + ","
+                    + Telephony.SimInfo.COLUMN_CARD_ID + " TEXT NOT NULL"
                     + ");");
         }
 
diff --git a/tests/src/com/android/providers/telephony/TelephonyProviderTest.java b/tests/src/com/android/providers/telephony/TelephonyProviderTest.java
index 47c1dc6..18c8d08 100644
--- a/tests/src/com/android/providers/telephony/TelephonyProviderTest.java
+++ b/tests/src/com/android/providers/telephony/TelephonyProviderTest.java
@@ -17,9 +17,12 @@
 package com.android.providers.telephony;
 
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.mock;
 
+
 import android.Manifest;
 import android.content.ContentUris;
 import android.content.ContentValues;
@@ -34,18 +37,17 @@
 import android.os.Process;
 import android.provider.Telephony;
 import android.provider.Telephony.Carriers;
+import android.provider.Telephony.SimInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.test.mock.MockContentResolver;
 import android.test.mock.MockContext;
 import android.test.suitebuilder.annotation.SmallTest;
+import android.text.TextUtils;
 import android.util.Log;
 
 import androidx.test.InstrumentationRegistry;
 
-import com.android.internal.telephony.uicc.IccRecords;
-import com.android.internal.telephony.uicc.UiccController;
-
 import junit.framework.TestCase;
 
 import org.junit.Test;
@@ -77,12 +79,6 @@
     private MockContentResolver mContentResolver;
     private TelephonyProviderTestable mTelephonyProviderTestable;
 
-    @Mock
-    private UiccController mUiccController;
-
-    @Mock
-    private IccRecords mIcRecords;
-
     private int notifyChangeCount;
     private int notifyChangeRestoreCount;
     private int notifyWfcCount;
@@ -93,6 +89,7 @@
     private static final String TEST_MCC = "123";
     private static final String TEST_MNC = "456";
     private static final String TEST_SPN = TelephonyProviderTestable.TEST_SPN;
+    private static final int TEST_CARRIERID = 1;
 
     // Used to test the path for URL_TELEPHONY_USING_SUBID with subid 1
     private static final Uri CONTENT_URI_WITH_SUBID = Uri.parse(
@@ -152,9 +149,7 @@
 
             doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(anyInt());
             doReturn(TEST_OPERATOR).when(mTelephonyManager).getSimOperator();
-            doReturn(mIcRecords).when(mUiccController).getIccRecords(anyInt(), anyInt());
-            doReturn(TEST_SPN).when(mIcRecords).getServiceProviderName();
-            doReturn(TEST_SPN).when(mIcRecords).getServiceProviderNameWithBrandOverride();
+            doReturn(TEST_CARRIERID).when(mTelephonyManager).getSimCarrierId();
 
             // Add authority="telephony" to given telephonyProvider
             ProviderInfo providerInfo = new ProviderInfo();
@@ -183,6 +178,16 @@
         }
 
         @Override
+        public String getSystemServiceName(Class<?> serviceClass) {
+            if (serviceClass.equals(TelephonyManager.class)) {
+              return Context.TELEPHONY_SERVICE;
+            } else {
+                Log.d(TAG, "getSystemServiceName: returning null");
+                return null;
+            }
+        }
+
+        @Override
         public Resources getResources() {
             Log.d(TAG, "getResources: returning null");
             return null;
@@ -220,7 +225,6 @@
         mTelephonyProviderTestable = new TelephonyProviderTestable();
         mContext = new MockContextWithProvider(mTelephonyProviderTestable);
         mContentResolver = (MockContentResolver) mContext.getContentResolver();
-        replaceInstance(UiccController.class, "mInstance", null, mUiccController);
         notifyChangeCount = 0;
         notifyChangeRestoreCount = 0;
     }
@@ -336,13 +340,13 @@
                     return cv;
         }).toArray(ContentValues[]::new);
 
-        mContentResolver.bulkInsert(SubscriptionManager.CONTENT_URI, existingSimInfoEntries);
+        mContentResolver.bulkInsert(SimInfo.CONTENT_URI, existingSimInfoEntries);
 
         // Run the upgrade helper on all the sim info entries.
         String[] proj = {SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID,
                 SubscriptionManager.MCC, SubscriptionManager.MNC,
                 SubscriptionManager.MCC_STRING, SubscriptionManager.MNC_STRING};
-        try (Cursor c = mContentResolver.query(SubscriptionManager.CONTENT_URI, proj,
+        try (Cursor c = mContentResolver.query(SimInfo.CONTENT_URI, proj,
                 null, null, null)) {
             while (c.moveToNext()) {
                 TelephonyProvider.fillInMccMncStringAtCursor(mContext,
@@ -351,7 +355,7 @@
         }
 
         // Loop through and make sure that everything got filled in correctly.
-        try (Cursor c = mContentResolver.query(SubscriptionManager.CONTENT_URI, proj,
+        try (Cursor c = mContentResolver.query(SimInfo.CONTENT_URI, proj,
                 null, null, null)) {
             while (c.moveToNext()) {
                 String mcc = c.getString(c.getColumnIndexOrThrow(SubscriptionManager.MCC_STRING));
@@ -554,7 +558,7 @@
         contentValues.put(SubscriptionManager.PROFILE_CLASS, insertProfileClass);
 
         Log.d(TAG, "testSimTable Inserting contentValues: " + contentValues);
-        mContentResolver.insert(SubscriptionManager.CONTENT_URI, contentValues);
+        mContentResolver.insert(SimInfo.CONTENT_URI, contentValues);
 
         // get values in table
         final String[] testProjection =
@@ -568,7 +572,7 @@
         String[] selectionArgs = { insertDisplayName };
         Log.d(TAG,"\ntestSimTable selection: " + selection
                 + "\ntestSimTable selectionArgs: " + selectionArgs.toString());
-        Cursor cursor = mContentResolver.query(SubscriptionManager.CONTENT_URI,
+        Cursor cursor = mContentResolver.query(SimInfo.CONTENT_URI,
                 testProjection, selection, selectionArgs, null);
 
         // verify that inserted values match results of query
@@ -589,12 +593,12 @@
         String[] selectionArgsToDelete = { insertDisplayName };
         Log.d(TAG, "testSimTable deleting selection: " + selectionToDelete
                 + "testSimTable selectionArgs: " + selectionArgs);
-        int numRowsDeleted = mContentResolver.delete(SubscriptionManager.CONTENT_URI,
+        int numRowsDeleted = mContentResolver.delete(SimInfo.CONTENT_URI,
                 selectionToDelete, selectionArgsToDelete);
         assertEquals(1, numRowsDeleted);
 
         // verify that deleted values are gone
-        cursor = mContentResolver.query(SubscriptionManager.CONTENT_URI,
+        cursor = mContentResolver.query(SimInfo.CONTENT_URI,
                 testProjection, selection, selectionArgs, null);
         assertEquals(0, cursor.getCount());
     }
@@ -1359,6 +1363,11 @@
         otherValues.put(Carriers.MVNO_TYPE, otherMvnoTyp);
         otherValues.put(Carriers.MVNO_MATCH_DATA, otherMvnoMatchData);
 
+        doReturn(true).when(telephonyManager).matchesCurrentSimOperator(
+            anyString(), anyInt(), eq(TelephonyProviderTestable.TEST_SPN));
+        doReturn(false).when(telephonyManager).matchesCurrentSimOperator(
+            anyString(), anyInt(), eq(otherMvnoMatchData));
+
         // insert APNs
         Log.d(TAG, "testRestoreDefaultApn: Bulk inserting contentValues=" + targetValues + ", "
                 + otherValues);
@@ -1440,54 +1449,46 @@
         contentValues.put(SubscriptionManager.CARD_ID, insertCardId);
 
         Log.d(TAG, "testSimTable Inserting wfc contentValues: " + contentValues);
-        mContentResolver.insert(SubscriptionManager.CONTENT_URI, contentValues);
+        mContentResolver.insert(SimInfo.CONTENT_URI, contentValues);
         assertEquals(0, notifyWfcCount);
 
         // update wfc_enabled
         ContentValues values = new ContentValues();
-        values.put(SubscriptionManager.WFC_IMS_ENABLED, true);
+        values.put(Telephony.SimInfo.COLUMN_WFC_IMS_ENABLED, true);
         final String selection = SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "=?";
         final String[] selectionArgs = { "" + insertSubId };
-        mContentResolver.update(SubscriptionManager.CONTENT_URI, values, selection, selectionArgs);
+        mContentResolver.update(SimInfo.CONTENT_URI, values, selection, selectionArgs);
         assertEquals(1, notifyWfcCount);
         assertEquals(0, notifyWfcCountWithTestSubId);
 
         // update other fields
         values = new ContentValues();
         values.put(SubscriptionManager.DISPLAY_NAME, "exampleDisplayNameNew");
-        mContentResolver.update(SubscriptionManager.CONTENT_URI, values, selection, selectionArgs);
+        mContentResolver.update(SimInfo.CONTENT_URI, values, selection, selectionArgs);
         // expect no change on wfc count
         assertEquals(1, notifyWfcCount);
         assertEquals(0, notifyWfcCountWithTestSubId);
 
         // update WFC using subId
         values = new ContentValues();
-        values.put(SubscriptionManager.WFC_IMS_ENABLED, false);
+        values.put(Telephony.SimInfo.COLUMN_WFC_IMS_ENABLED, false);
         mContentResolver.update(SubscriptionManager.getUriForSubscriptionId(insertSubId),
                 values, null, null);
         assertEquals(1, notifyWfcCount);
         assertEquals(0, notifyWfcCountWithTestSubId);
     }
 
-    protected void replaceInstance(final Class c, final String instanceName,
-            final Object obj, final Object newValue)
-            throws Exception {
-        Field field = c.getDeclaredField(instanceName);
-        field.setAccessible(true);
-        field.set(obj, newValue);
-    }
-
     @Test
     @SmallTest
-    public void testSIMAPNLIST_APNMatchTheMCCMNCAndMVNO() {
-        // Test on getCurrentAPNList() step 1
+    public void testSIMAPNLIST_MatchTheMVNOAPN() {
+        // Test on getSubscriptionMatchingAPNList() step 1
         final String apnName = "apnName";
         final String carrierName = "name";
         final String numeric = TEST_OPERATOR;
         final String mvnoType = "spn";
         final String mvnoData = TEST_SPN;
 
-        // Insert the APN and DB only have the MCC/MNC and MVNO APN
+        // Insert the MVNO APN
         ContentValues contentValues = new ContentValues();
         contentValues.put(Carriers.APN, apnName);
         contentValues.put(Carriers.NAME, carrierName);
@@ -1496,6 +1497,20 @@
         contentValues.put(Carriers.MVNO_MATCH_DATA, mvnoData);
         mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
 
+        // Insert the MNO APN
+        contentValues = new ContentValues();
+        contentValues.put(Carriers.APN, apnName);
+        contentValues.put(Carriers.NAME, carrierName);
+        contentValues.put(Carriers.NUMERIC, numeric);
+        mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
+
+        TelephonyManager telephonyManager =
+            (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+        doReturn(true).when(telephonyManager).matchesCurrentSimOperator(
+            anyString(), anyInt(), eq(mvnoData));
+        doReturn(false).when(telephonyManager).matchesCurrentSimOperator(
+            anyString(), anyInt(), eq(""));
+
         // Query DB
         final String[] testProjection =
                 {
@@ -1507,7 +1522,9 @@
         Cursor cursor = mContentResolver.query(URL_SIM_APN_LIST,
                 testProjection, null, null, null);
 
+        // When the DB has MVNO and MNO APN, the query based on SIM_APN_LIST will return MVNO APN
         cursor.moveToFirst();
+        assertEquals(cursor.getCount(), 1);
         assertEquals(apnName, cursor.getString(0));
         assertEquals(carrierName, cursor.getString(1));
         assertEquals(numeric, cursor.getString(2));
@@ -1516,13 +1533,13 @@
 
     @Test
     @SmallTest
-    public void testSIMAPNLIST_APNMatchTheParentMCCMNC() {
-        // Test on getCurrentAPNList() step 2
+    public void testSIMAPNLIST_MatchTheMNOAPN() {
+        // Test on getSubscriptionMatchingAPNList() step 2
         final String apnName = "apnName";
         final String carrierName = "name";
         final String numeric = TEST_OPERATOR;
 
-        // Insert the APN and DB only have the MNO APN
+        // Insert the MNO APN
         ContentValues contentValues = new ContentValues();
         contentValues.put(Carriers.APN, apnName);
         contentValues.put(Carriers.NAME, carrierName);
@@ -1544,4 +1561,91 @@
         assertEquals(carrierName, cursor.getString(1));
         assertEquals(numeric, cursor.getString(2));
     }
+
+    @Test
+    @SmallTest
+    public void testSIMAPNLIST_MatchTheCarrierIDANDMNOAPN() {
+        // Test on getSubscriptionMatchingAPNList() will return the {MCCMNC}
+        final String apnName = "apnName";
+        final String carrierName = "name";
+        final int carrierId = TEST_CARRIERID;
+
+        // Add the APN that only have carrier id
+        ContentValues contentValues = new ContentValues();
+        contentValues.put(Carriers.APN, apnName);
+        contentValues.put(Carriers.NAME, carrierName);
+        contentValues.put(Carriers.CARRIER_ID, carrierId);
+        mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
+
+        // Add MNO APN that added by user
+        contentValues = new ContentValues();
+        contentValues.put(Carriers.APN, apnName);
+        contentValues.put(Carriers.NAME, carrierName);
+        contentValues.put(Carriers.NUMERIC, TEST_OPERATOR);
+        contentValues.put(Carriers.EDITED_STATUS, Carriers.UNEDITED);
+        mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
+
+        // Query DB
+        final String[] testProjection =
+            {
+                Carriers.APN,
+                Carriers.NAME,
+                Carriers.CARRIER_ID,
+            };
+        Cursor cursor = mContentResolver.query(URL_SIM_APN_LIST, testProjection, null, null, null);
+
+        // The query based on SIM_APN_LIST will return MNO APN and the APN that has carrier id
+        assertEquals(cursor.getCount(), 2);
+    }
+
+    @Test
+    @SmallTest
+    public void testSIMAPNLIST_MatchTheCarrierAPNAndMVNOAPN() {
+        final String apnName = "apnName";
+        final String carrierName = "name";
+        final String mvnoType = "spn";
+        final String mvnoData = TEST_SPN;
+        final int carrierId = TEST_CARRIERID;
+
+        // Add the APN that only have carrier id
+        ContentValues contentValues = new ContentValues();
+        contentValues.put(Carriers.APN, apnName);
+        contentValues.put(Carriers.NAME, carrierName);
+        contentValues.put(Carriers.CARRIER_ID, carrierId);
+        mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
+
+        // Add MVNO APN that added by user
+        contentValues = new ContentValues();
+        contentValues.put(Carriers.APN, apnName);
+        contentValues.put(Carriers.NAME, carrierName);
+        contentValues.put(Carriers.NUMERIC, TEST_OPERATOR);
+        contentValues.put(Carriers.MVNO_TYPE, mvnoType);
+        contentValues.put(Carriers.MVNO_MATCH_DATA, mvnoData);
+        mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
+
+        // Add MNO APN that added by user
+        contentValues = new ContentValues();
+        contentValues.put(Carriers.APN, apnName);
+        contentValues.put(Carriers.NAME, carrierName);
+        contentValues.put(Carriers.NUMERIC, TEST_OPERATOR);
+        mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
+
+        // Query DB
+        final String[] testProjection =
+            {
+                Carriers.APN,
+                Carriers.NAME,
+                Carriers.CARRIER_ID,
+                Carriers.MVNO_TYPE,
+            };
+        Cursor cursor = mContentResolver.query(URL_SIM_APN_LIST,
+            testProjection, null, null, null);
+
+        // The query based on SIM_APN_LIST will return MVNO APN and the APN that has carrier id
+        assertEquals(cursor.getCount(), 2);
+        while(cursor.moveToNext()) {
+            assertTrue(!TextUtils.isEmpty(cursor.getString(2))
+                    || !TextUtils.isEmpty(cursor.getString(3)));
+        }
+    }
 }
diff --git a/tests/src/com/android/providers/telephony/TelephonyProviderTestable.java b/tests/src/com/android/providers/telephony/TelephonyProviderTestable.java
index d9f6ee3..eca7830 100644
--- a/tests/src/com/android/providers/telephony/TelephonyProviderTestable.java
+++ b/tests/src/com/android/providers/telephony/TelephonyProviderTestable.java
@@ -27,7 +27,6 @@
 import androidx.test.InstrumentationRegistry;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.telephony.uicc.IccRecords;
 import com.android.providers.telephony.TelephonyProvider;
 
 /**
@@ -87,15 +86,6 @@
         return false;
     }
 
-    @Override
-    IccRecords getIccRecords(int subId) {
-        Log.d(TAG, "getIccRecords called");
-        IccRecords iccRecords = mock(IccRecords.class);
-        doReturn(TEST_SPN).when(iccRecords).getServiceProviderName();
-        doReturn(TEST_SPN).when(iccRecords).getServiceProviderNameWithBrandOverride();
-        return iccRecords;
-    }
-
     public void fakeCallingUid(int uid) {
         mMockInjector.fakeCallingUid(uid);
     }