[automerger skipped] Merge "[Telephony Mainline] Use the new SystemApi for mainline" am: 0e79e43d0f am: 963cbf575b am: 425cff82d3 -s ours
am skip reason: Change-Id I644ea6f9ac0e2c7e3222a07a6eff59d6b38831a2 with SHA-1 d48723b950 is in history

Change-Id: I884d22052830381dfabc45a443d5c4c339570efb
diff --git a/Android.bp b/Android.bp
index eabd567..c7ecd27 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,9 +1,9 @@
 android_app {
     name: "TelephonyProvider",
     privileged: true,
-    srcs: ["src/**/*.java"],
+    srcs: ["src/**/*.java", "proto/**/*.proto"],
     platform_apis: true,
     certificate: "platform",
     libs: ["telephony-common"],
-    static_libs: ["android-common"],
+    static_libs: ["android-common", "telephonyprovider-protos"],
 }
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index d8565eb..3a266e0 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -52,13 +52,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. -->
diff --git a/proto/Android.bp b/proto/Android.bp
new file mode 100644
index 0000000..4420263
--- /dev/null
+++ b/proto/Android.bp
@@ -0,0 +1,29 @@
+// 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.
+
+java_library_static {
+    name: "telephonyprovider-protos",
+    proto: {
+        type: "nano",
+        output_params: [
+            "store_unknown_fields=true",
+            "enum_style=java",
+        ],
+    },
+    srcs: ["src/**/*.proto"],
+    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-fr/strings.xml b/res/values-fr/strings.xml
index 6cfcdfb..f3baf24 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -17,5 +17,5 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" product="tablet" msgid="9194799012395299737">"Configuration du réseau mobile"</string>
-    <string name="app_label" product="default" msgid="8338087656149558019">"Stockage tél. et SMS/MMS"</string>
+    <string name="app_label" product="default" msgid="8338087656149558019">"Téléphone et stockage des messages"</string>
 </resources>
diff --git a/src/com/android/providers/telephony/CarrierIdProvider.java b/src/com/android/providers/telephony/CarrierIdProvider.java
index 44f053d..122c304 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.getActiveAndHiddenSubscriptionInfoList();
+            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/MmsProvider.java b/src/com/android/providers/telephony/MmsProvider.java
index 30158c3..96059d7 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;
@@ -44,6 +43,8 @@
 import android.provider.Telephony.Mms.Rate;
 import android.provider.Telephony.MmsSms;
 import android.provider.Telephony.Threads;
+import android.system.ErrnoException;
+import android.system.Os;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -518,9 +519,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);
@@ -816,10 +821,13 @@
                 String path = getContext().getDir(PARTS_DIR_NAME, 0).getPath() + '/' +
                         uri.getPathSegments().get(1);
                 // Reset the file permission back to read for everyone but me.
-                int result = FileUtils.setPermissions(path, 0644, -1, -1);
-                if (LOCAL_LOGV) {
-                    Log.d(TAG, "MmsProvider.update setPermissions result: " + result +
-                            " for path: " + path);
+                try {
+                    Os.chmod(path, 0644);
+                    if (LOCAL_LOGV) {
+                        Log.d(TAG, "MmsProvider.update chmod is successful for path: " + path);
+                    }
+                } catch (ErrnoException e) {
+                    Log.e(TAG, "Exception in chmod: " + e);
                 }
                 return 0;
 
diff --git a/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java b/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
index d5aa308..83d9d7a 100644
--- a/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
+++ b/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
@@ -47,7 +47,6 @@
 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.google.android.mms.pdu.EncodedStringValue;
@@ -266,7 +265,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
@@ -556,7 +555,7 @@
     }
 
     private static void localLogWtf(String logMsg) {
-        Slog.wtf(TAG, logMsg);
+        Log.wtf(TAG, logMsg);
     }
 
     private boolean isInitialCreateDone() {
diff --git a/src/com/android/providers/telephony/ServiceStateProvider.java b/src/com/android/providers/telephony/ServiceStateProvider.java
deleted file mode 100644
index f707200..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.getOperatorAlphaLong();
-            final String voice_operator_alpha_short = ss.getOperatorAlphaShort();
-            final String voice_operator_numeric = ss.getOperatorNumeric();
-            final String data_operator_alpha_long = ss.getOperatorAlphaLong();
-            final String data_operator_alpha_short = ss.getOperatorAlphaShort();
-            final String data_operator_numeric = ss.getOperatorNumeric();
-            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/TelephonyBackupAgent.java b/src/com/android/providers/telephony/TelephonyBackupAgent.java
index b3c0d99..3d32bef 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;
@@ -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
@@ -710,7 +710,8 @@
                 subscriptionInfo.getCountryIso().toUpperCase(Locale.US));
     }
 
-    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 +734,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 +843,8 @@
                 default:
                     if (DEBUG) {
                         Log.w(TAG, "readSmsValuesFromReader Unknown name:" + name);
+                    } else {
+                        Log.w(TAG, "readSmsValuesFromReader encountered unknown name.");
                     }
                     jsonReader.skipValue();
                     break;
@@ -843,12 +865,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 +900,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 +924,7 @@
             writeStringToWriter(jsonWriter, cursor, Telephony.Mms.SUBJECT_CHARSET);
         }
         jsonWriter.endObject();
-        return 1;
+        chunk.count++;
     }
 
     private Mms readMmsFromReader(JsonReader jsonReader) throws IOException {
@@ -955,9 +983,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 +1021,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 +1090,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 +1121,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 +1130,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 +1158,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 +1178,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 +1198,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 +1207,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 +1311,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 +1385,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 +1401,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 +1411,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 +1420,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 +1440,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 6c25832..2e0b972 100644
--- a/src/com/android/providers/telephony/TelephonyProvider.java
+++ b/src/com/android/providers/telephony/TelephonyProvider.java
@@ -94,15 +94,14 @@
 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;
@@ -114,6 +113,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.compat.IPlatformCompat;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.uicc.UiccController;
 import com.android.internal.util.XmlUtils;
@@ -124,6 +124,7 @@
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
+import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileReader;
 import java.io.IOException;
@@ -136,6 +137,7 @@
 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
@@ -237,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.UNIQUE_KEY_SUBSCRIPTION_ID + " ASC";
 
     private static final int INVALID_APN_ID = -1;
     private static final List<String> CARRIERS_UNIQUE_FIELDS = new ArrayList<String>();
@@ -254,6 +256,55 @@
 
     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 {
@@ -355,67 +406,66 @@
     @VisibleForTesting
     public static String getStringForSimInfoTableCreation(String tableName) {
         return "CREATE TABLE " + tableName + "("
-                + SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID
+                + Telephony.SimInfo.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,"
-                + SubscriptionManager.UICC_APPLICATIONS_ENABLED + " INTEGER DEFAULT 1"
+                + Telephony.SimInfo.ICC_ID + " TEXT NOT NULL,"
+                + Telephony.SimInfo.SIM_SLOT_INDEX
+                + " INTEGER DEFAULT " + Telephony.SimInfo.SIM_NOT_INSERTED + ","
+                + Telephony.SimInfo.DISPLAY_NAME + " TEXT,"
+                + Telephony.SimInfo.CARRIER_NAME + " TEXT,"
+                + Telephony.SimInfo.NAME_SOURCE
+                + " INTEGER DEFAULT " + Telephony.SimInfo.NAME_SOURCE_DEFAULT + ","
+                + Telephony.SimInfo.COLOR + " INTEGER DEFAULT "
+                + Telephony.SimInfo.COLOR_DEFAULT + ","
+                + Telephony.SimInfo.NUMBER + " TEXT,"
+                + Telephony.SimInfo.DISPLAY_NUMBER_FORMAT
+                + " INTEGER NOT NULL DEFAULT " + Telephony.SimInfo.DISPLAY_NUMBER_DEFAULT + ","
+                + Telephony.SimInfo.DATA_ROAMING
+                + " INTEGER DEFAULT " + Telephony.SimInfo.DATA_ROAMING_DEFAULT + ","
+                + Telephony.SimInfo.MCC + " INTEGER DEFAULT 0,"
+                + Telephony.SimInfo.MNC + " INTEGER DEFAULT 0,"
+                + Telephony.SimInfo.MCC_STRING + " TEXT,"
+                + Telephony.SimInfo.MNC_STRING + " TEXT,"
+                + Telephony.SimInfo.EHPLMNS + " TEXT,"
+                + Telephony.SimInfo.HPLMNS + " TEXT,"
+                + Telephony.SimInfo.SIM_PROVISIONING_STATUS
+                + " INTEGER DEFAULT " + Telephony.SimInfo.SIM_PROVISIONED + ","
+                + Telephony.SimInfo.IS_EMBEDDED + " INTEGER DEFAULT 0,"
+                + Telephony.SimInfo.CARD_ID + " TEXT NOT NULL,"
+                + Telephony.SimInfo.ACCESS_RULES + " BLOB,"
+                + Telephony.SimInfo.ACCESS_RULES_FROM_CARRIER_CONFIGS + " BLOB,"
+                + Telephony.SimInfo.IS_REMOVABLE + " INTEGER DEFAULT 0,"
+                + Telephony.SimInfo.CB_EXTREME_THREAT_ALERT + " INTEGER DEFAULT 1,"
+                + Telephony.SimInfo.CB_SEVERE_THREAT_ALERT + " INTEGER DEFAULT 1,"
+                + Telephony.SimInfo.CB_AMBER_ALERT + " INTEGER DEFAULT 1,"
+                + Telephony.SimInfo.CB_EMERGENCY_ALERT + " INTEGER DEFAULT 1,"
+                + Telephony.SimInfo.CB_ALERT_SOUND_DURATION + " INTEGER DEFAULT 4,"
+                + Telephony.SimInfo.CB_ALERT_REMINDER_INTERVAL + " INTEGER DEFAULT 0,"
+                + Telephony.SimInfo.CB_ALERT_VIBRATE + " INTEGER DEFAULT 1,"
+                + Telephony.SimInfo.CB_ALERT_SPEECH + " INTEGER DEFAULT 1,"
+                + Telephony.SimInfo.CB_ETWS_TEST_ALERT + " INTEGER DEFAULT 0,"
+                + Telephony.SimInfo.CB_CHANNEL_50_ALERT + " INTEGER DEFAULT 1,"
+                + Telephony.SimInfo.CB_CMAS_TEST_ALERT + " INTEGER DEFAULT 0,"
+                + Telephony.SimInfo.CB_OPT_OUT_DIALOG + " INTEGER DEFAULT 1,"
+                + Telephony.SimInfo.ENHANCED_4G_MODE_ENABLED + " INTEGER DEFAULT -1,"
+                + Telephony.SimInfo.VT_IMS_ENABLED + " INTEGER DEFAULT -1,"
+                + Telephony.SimInfo.WFC_IMS_ENABLED + " INTEGER DEFAULT -1,"
+                + Telephony.SimInfo.WFC_IMS_MODE + " INTEGER DEFAULT -1,"
+                + Telephony.SimInfo.WFC_IMS_ROAMING_MODE + " INTEGER DEFAULT -1,"
+                + Telephony.SimInfo.WFC_IMS_ROAMING_ENABLED + " INTEGER DEFAULT -1,"
+                + Telephony.SimInfo.IS_OPPORTUNISTIC + " INTEGER DEFAULT 0,"
+                + Telephony.SimInfo.GROUP_UUID + " TEXT,"
+                + Telephony.SimInfo.IS_METERED + " INTEGER DEFAULT 1,"
+                + Telephony.SimInfo.ISO_COUNTRY_CODE + " TEXT,"
+                + Telephony.SimInfo.CARRIER_ID + " INTEGER DEFAULT -1,"
+                + Telephony.SimInfo.PROFILE_CLASS + " INTEGER DEFAULT "
+                + Telephony.SimInfo.PROFILE_CLASS_DEFAULT + ","
+                + Telephony.SimInfo.SUBSCRIPTION_TYPE + " INTEGER DEFAULT "
+                + Telephony.SimInfo.SUBSCRIPTION_TYPE_LOCAL_SIM + ","
+                + Telephony.SimInfo.GROUP_OWNER + " TEXT,"
+                + Telephony.SimInfo.DATA_ENABLED_OVERRIDE_RULES + " TEXT,"
+                + Telephony.SimInfo.IMSI + " TEXT,"
+                + Telephony.SimInfo.UICC_APPLICATIONS_ENABLED + " INTEGER DEFAULT 1"
                 + ");";
     }
 
@@ -597,10 +647,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) {
@@ -612,14 +670,14 @@
             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 byte[] toByteArray(InputStream input) throws IOException {
@@ -853,9 +911,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.MCC + " INTEGER DEFAULT 0;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE +
-                            " ADD COLUMN " + SubscriptionManager.MNC + " INTEGER DEFAULT 0;");
+                            " ADD COLUMN " + Telephony.SimInfo.MNC + " INTEGER DEFAULT 0;");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -868,7 +926,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.CARRIER_NAME + " TEXT DEFAULT '';");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -951,29 +1009,29 @@
                     // 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.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.CB_SEVERE_THREAT_ALERT + " INTEGER DEFAULT 1;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.CB_AMBER_ALERT + " INTEGER DEFAULT 1;");
+                            + Telephony.SimInfo.CB_AMBER_ALERT + " INTEGER DEFAULT 1;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.CB_EMERGENCY_ALERT + " INTEGER DEFAULT 1;");
+                            + Telephony.SimInfo.CB_EMERGENCY_ALERT + " INTEGER DEFAULT 1;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.CB_ALERT_SOUND_DURATION + " INTEGER DEFAULT 4;");
+                            + Telephony.SimInfo.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.CB_ALERT_REMINDER_INTERVAL + " INTEGER DEFAULT 0;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.CB_ALERT_VIBRATE + " INTEGER DEFAULT 1;");
+                            + Telephony.SimInfo.CB_ALERT_VIBRATE + " INTEGER DEFAULT 1;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.CB_ALERT_SPEECH + " INTEGER DEFAULT 1;");
+                            + Telephony.SimInfo.CB_ALERT_SPEECH + " INTEGER DEFAULT 1;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.CB_ETWS_TEST_ALERT + " INTEGER DEFAULT 0;");
+                            + Telephony.SimInfo.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.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.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.CB_OPT_OUT_DIALOG + " INTEGER DEFAULT 1;");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -1007,8 +1065,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.SIM_PROVISIONING_STATUS + " INTEGER DEFAULT " +
+                            Telephony.SimInfo.SIM_PROVISIONED + ";");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -1026,11 +1084,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.IS_EMBEDDED + " INTEGER DEFAULT 0;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " +
-                            SubscriptionManager.ACCESS_RULES + " BLOB;");
+                            Telephony.SimInfo.ACCESS_RULES + " BLOB;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " +
-                            SubscriptionManager.IS_REMOVABLE + " INTEGER DEFAULT 0;");
+                            Telephony.SimInfo.IS_REMOVABLE + " INTEGER DEFAULT 0;");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -1058,18 +1116,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.ENHANCED_4G_MODE_ENABLED
                             + " INTEGER DEFAULT -1;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.VT_IMS_ENABLED + " INTEGER DEFAULT -1;");
+                            + Telephony.SimInfo.VT_IMS_ENABLED + " INTEGER DEFAULT -1;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.WFC_IMS_ENABLED + " INTEGER DEFAULT -1;");
+                            + Telephony.SimInfo.WFC_IMS_ENABLED + " INTEGER DEFAULT -1;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.WFC_IMS_MODE + " INTEGER DEFAULT -1;");
+                            + Telephony.SimInfo.WFC_IMS_MODE + " INTEGER DEFAULT -1;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.WFC_IMS_ROAMING_MODE + " INTEGER DEFAULT -1;");
+                            + Telephony.SimInfo.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.WFC_IMS_ROAMING_ENABLED + " INTEGER DEFAULT -1;");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + CARRIERS_TABLE + " upgrade. " +
@@ -1113,17 +1171,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.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",
+                    c = db.query(SIMINFO_TABLE, proj, Telephony.SimInfo.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.CARD_ID + ": " + c.getCount());
                     c.close();
                 }
                 oldVersion = 25 << 16 | 6;
@@ -1149,9 +1207,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.MCC_STRING + " TEXT;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE +
-                            " ADD COLUMN " + SubscriptionManager.MNC_STRING + " TEXT;");
+                            " ADD COLUMN " + Telephony.SimInfo.MNC_STRING + " TEXT;");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -1159,8 +1217,8 @@
                     }
                 }
                 // Migrate the old integer values over to strings
-                String[] proj = {SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID,
-                        SubscriptionManager.MCC, SubscriptionManager.MNC};
+                String[] proj = {Telephony.SimInfo.UNIQUE_KEY_SUBSCRIPTION_ID,
+                        Telephony.SimInfo.MCC, Telephony.SimInfo.MNC};
                 try (Cursor c = db.query(SIMINFO_TABLE, proj, null, null, null, null, null)) {
                     while (c.moveToNext()) {
                         fillInMccMncStringAtCursor(mContext, db, c);
@@ -1173,7 +1231,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.IS_OPPORTUNISTIC + " INTEGER DEFAULT 0;");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -1203,7 +1261,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.GROUP_UUID + " TEXT;");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -1217,7 +1275,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.IS_METERED + " INTEGER DEFAULT 1;");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -1231,7 +1289,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.ISO_COUNTRY_CODE + " TEXT;");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -1245,7 +1303,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.CARRIER_ID + " INTEGER DEFAULT -1;");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -1259,8 +1317,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.PROFILE_CLASS + " INTEGER DEFAULT " +
+                            Telephony.SimInfo.PROFILE_CLASS_DEFAULT + ";");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -1274,8 +1332,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.SUBSCRIPTION_TYPE + " INTEGER DEFAULT "
+                        + Telephony.SimInfo.SUBSCRIPTION_TYPE_LOCAL_SIM + ";");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -1301,13 +1359,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.EHPLMNS + " TEXT;");
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE +
-                            " ADD COLUMN " + SubscriptionManager.HPLMNS + " TEXT;");
+                            " ADD COLUMN " + Telephony.SimInfo.HPLMNS + " TEXT;");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade for ehplmns. " +
@@ -1317,25 +1375,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.GROUP_OWNER + " TEXT;");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -1349,7 +1393,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.DATA_ENABLED_OVERRIDE_RULES + " TEXT;");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -1363,7 +1407,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.IMSI + " TEXT;");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -1377,7 +1421,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.ACCESS_RULES_FROM_CARRIER_CONFIGS + " BLOB;");
                 } catch (SQLiteException e) {
                     if (DBG) {
                         log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
@@ -1390,7 +1434,7 @@
                 try {
                     // Try to update the siminfo table. It might not be there.
                     db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
-                            + SubscriptionManager.UICC_APPLICATIONS_ENABLED
+                            + Telephony.SimInfo.UICC_APPLICATIONS_ENABLED
                             + " INTEGER DEFAULT 1;");
                 } catch (SQLiteException e) {
                     if (DBG) {
@@ -1465,51 +1509,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.ICC_ID);
+            getStringValueFromCursor(cv, c, Telephony.SimInfo.DISPLAY_NAME);
+            getStringValueFromCursor(cv, c, Telephony.SimInfo.CARRIER_NAME);
+            getStringValueFromCursor(cv, c, Telephony.SimInfo.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.SIM_SLOT_INDEX);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.NAME_SOURCE);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.COLOR);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.DISPLAY_NUMBER_FORMAT);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.DATA_ROAMING);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.MCC);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.MNC);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.SIM_PROVISIONING_STATUS);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.IS_EMBEDDED);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.IS_REMOVABLE);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.CB_EXTREME_THREAT_ALERT);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.CB_SEVERE_THREAT_ALERT);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.CB_AMBER_ALERT);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.CB_EMERGENCY_ALERT);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.CB_ALERT_SOUND_DURATION);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.CB_ALERT_REMINDER_INTERVAL);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.CB_ALERT_VIBRATE);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.CB_ALERT_SPEECH);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.CB_ETWS_TEST_ALERT);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.CB_CHANNEL_50_ALERT);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.CB_CMAS_TEST_ALERT);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.CB_OPT_OUT_DIALOG);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.ENHANCED_4G_MODE_ENABLED);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.VT_IMS_ENABLED);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.WFC_IMS_ENABLED);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.WFC_IMS_MODE);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.WFC_IMS_ROAMING_MODE);
+            getIntValueFromCursor(cv, c, Telephony.SimInfo.WFC_IMS_ROAMING_ENABLED);
 
             // Blob vals
-            getBlobValueFromCursor(cv, c, SubscriptionManager.ACCESS_RULES);
+            getBlobValueFromCursor(cv, c, Telephony.SimInfo.ACCESS_RULES);
         }
 
         private void getCardIdfromIccid(ContentValues cv, Cursor c) {
-            int columnIndex = c.getColumnIndex(SubscriptionManager.ICC_ID);
+            int columnIndex = c.getColumnIndex(Telephony.SimInfo.ICC_ID);
             if (columnIndex != -1) {
                 String fromCursor = c.getString(columnIndex);
                 if (!TextUtils.isEmpty(fromCursor)) {
-                    cv.put(SubscriptionManager.CARD_ID, fromCursor);
+                    cv.put(Telephony.SimInfo.CARD_ID, fromCursor);
                 }
             }
         }
@@ -1858,13 +1902,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);
                         }
 
@@ -1952,8 +1994,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;
@@ -1963,8 +2004,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));
                 }
             }
@@ -2056,22 +2096,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);
@@ -3770,33 +3808,33 @@
                                     | 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.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.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.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.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.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.WFC_IMS_ROAMING_ENABLED)) {
                         getContext().getContentResolver().notifyChange(getNotifyContentUri(
                                 SubscriptionManager.WFC_ROAMING_ENABLED_CONTENT_URI,
                                 usingSubId, subId), null, true, UserHandle.USER_ALL);
@@ -3833,16 +3871,20 @@
                 return;
             }
         }
-        throw new SecurityException("No permission to write APN settings");
-    }
 
-    private void checkPhonePrivilegePermission() {
-        int status = getContext().checkCallingOrSelfPermission(
-                "android.permission.READ_PRIVILEGED_PHONE_STATE");
-        if (status == PackageManager.PERMISSION_GRANTED) {
-            return;
+        IPlatformCompat platformCompat = IPlatformCompat.Stub.asInterface(
+                ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
+        if (platformCompat != null) {
+            try {
+                platformCompat.reportChangeByUid(
+                        Telephony.Carriers.APN_READING_PERMISSION_CHANGE_ID,
+                        Binder.getCallingUid());
+            } catch (RemoteException e) {
+                //ignore
+            }
         }
-        throw new SecurityException("No phone privilege permission");
+
+        throw new SecurityException("No permission to access APN settings");
     }
 
     private DatabaseHelper mOpenHelper;
@@ -3958,10 +4000,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.MCC));
+            mnc = c.getInt(c.getColumnIndexOrThrow(Telephony.SimInfo.MNC));
             subId = c.getString(c.getColumnIndexOrThrow(
-                    SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID));
+                    Telephony.SimInfo.UNIQUE_KEY_SUBSCRIPTION_ID));
         } catch (IllegalArgumentException e) {
             Log.e(TAG, "Possible database corruption -- some columns not found.");
             return;
@@ -3970,10 +4012,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.MCC_STRING, mccString);
+        cv.put(Telephony.SimInfo.MNC_STRING, mncString);
         db.update(SIMINFO_TABLE, cv,
-                SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "=?",
+                Telephony.SimInfo.UNIQUE_KEY_SUBSCRIPTION_ID + "=?",
                 new String[]{subId});
     }
 
@@ -4010,17 +4052,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);
             }
@@ -4045,4 +4087,135 @@
         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/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/ServiceStateProviderTest.java b/tests/src/com/android/providers/telephony/ServiceStateProviderTest.java
deleted file mode 100644
index 0cd66e3..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.getOperatorAlphaLong();
-        final String voiceOperatorAlphaShort = ss.getOperatorAlphaShort();
-        final String voiceOperatorNumeric = ss.getOperatorNumeric();
-        final String dataOperatorAlphaLong = ss.getOperatorAlphaLong();
-        final String dataOperatorAlphaShort = ss.getOperatorAlphaShort();
-        final String dataOperatorNumeric = ss.getOperatorNumeric();
-        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 26df3c0..8ddd7f7 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;
@@ -242,22 +243,22 @@
             Log.d(TAG, "InMemoryTelephonyProviderV5DbHelper onCreate creating the siminfo table");
             db.execSQL(
                     "CREATE TABLE siminfo ("
-                    + SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID
+                    + Telephony.SimInfo.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.ICC_ID + " TEXT NOT NULL,"
+                    + Telephony.SimInfo.SIM_SLOT_INDEX
+                        + " INTEGER DEFAULT " + Telephony.SimInfo.SIM_NOT_INSERTED + ","
+                    + Telephony.SimInfo.DISPLAY_NAME + " TEXT,"
+                    + Telephony.SimInfo.NAME_SOURCE
+                        + " INTEGER DEFAULT " + Telephony.SimInfo.NAME_SOURCE_DEFAULT + ","
+                    + Telephony.SimInfo.COLOR
+                        + " INTEGER DEFAULT " + Telephony.SimInfo.COLOR_DEFAULT + ","
+                    + Telephony.SimInfo.NUMBER + " TEXT,"
+                    + Telephony.SimInfo.DISPLAY_NUMBER_FORMAT + " INTEGER NOT NULL"
+                        + " DEFAULT " + Telephony.SimInfo.DISPLAY_NUMBER_DEFAULT + ","
+                    + Telephony.SimInfo.DATA_ROAMING
+                        + " INTEGER DEFAULT " + Telephony.SimInfo.DATA_ROAMING_DEFAULT + ","
+                    + Telephony.SimInfo.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 efd5120..340e2af 100644
--- a/tests/src/com/android/providers/telephony/TelephonyProviderTest.java
+++ b/tests/src/com/android/providers/telephony/TelephonyProviderTest.java
@@ -1454,7 +1454,7 @@
 
         // update wfc_enabled
         ContentValues values = new ContentValues();
-        values.put(SubscriptionManager.WFC_IMS_ENABLED, true);
+        values.put(Telephony.SimInfo.WFC_IMS_ENABLED, true);
         final String selection = SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "=?";
         final String[] selectionArgs = { "" + insertSubId };
         mContentResolver.update(SimInfo.CONTENT_URI, values, selection, selectionArgs);
@@ -1471,7 +1471,7 @@
 
         // update WFC using subId
         values = new ContentValues();
-        values.put(SubscriptionManager.WFC_IMS_ENABLED, false);
+        values.put(Telephony.SimInfo.WFC_IMS_ENABLED, false);
         mContentResolver.update(SubscriptionManager.getUriForSubscriptionId(insertSubId),
                 values, null, null);
         assertEquals(1, notifyWfcCount);