diff --git a/src/com/android/phone/SimPhonebookProvider.java b/src/com/android/phone/SimPhonebookProvider.java
new file mode 100644
index 0000000..8307672
--- /dev/null
+++ b/src/com/android/phone/SimPhonebookProvider.java
@@ -0,0 +1,932 @@
+/*
+ * Copyright (C) 2020 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.phone;
+
+import android.Manifest;
+import android.annotation.TestApi;
+import android.content.ContentProvider;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.UriMatcher;
+import android.content.pm.PackageManager;
+import android.database.ContentObserver;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.CancellationSignal;
+import android.os.RemoteException;
+import android.provider.SimPhonebookContract;
+import android.provider.SimPhonebookContract.ElementaryFiles;
+import android.provider.SimPhonebookContract.SimRecords;
+import android.telephony.PhoneNumberUtils;
+import android.telephony.Rlog;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyFrameworkInitializer;
+import android.telephony.TelephonyManager;
+import android.util.ArraySet;
+import android.util.Pair;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.IIccPhoneBook;
+import com.android.internal.telephony.uicc.AdnRecord;
+import com.android.internal.telephony.uicc.IccConstants;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.util.concurrent.MoreExecutors;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.function.Supplier;
+
+/**
+ * Provider for contact records stored on the SIM card.
+ *
+ * @see SimPhonebookContract
+ */
+public class SimPhonebookProvider extends ContentProvider {
+
+    @VisibleForTesting
+    static final String[] ELEMENTARY_FILES_ALL_COLUMNS = {
+            ElementaryFiles.SLOT_INDEX,
+            ElementaryFiles.SUBSCRIPTION_ID,
+            ElementaryFiles.EF_TYPE,
+            ElementaryFiles.MAX_RECORDS,
+            ElementaryFiles.RECORD_COUNT,
+            ElementaryFiles.NAME_MAX_LENGTH,
+            ElementaryFiles.PHONE_NUMBER_MAX_LENGTH
+    };
+    @VisibleForTesting
+    static final String[] SIM_RECORDS_ALL_COLUMNS = {
+            SimRecords.SUBSCRIPTION_ID,
+            SimRecords.ELEMENTARY_FILE_TYPE,
+            SimRecords.RECORD_NUMBER,
+            SimRecords.NAME,
+            SimRecords.PHONE_NUMBER
+    };
+    private static final String TAG = "SimPhonebookProvider";
+    private static final Set<String> ELEMENTARY_FILES_COLUMNS_SET =
+            ImmutableSet.copyOf(ELEMENTARY_FILES_ALL_COLUMNS);
+    private static final Set<String> SIM_RECORDS_WRITABLE_COLUMNS = ImmutableSet.of(
+            SimRecords.NAME, SimRecords.PHONE_NUMBER
+    );
+
+    private static final int WRITE_TIMEOUT_SECONDS = 30;
+
+    private static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
+
+    private static final int ELEMENTARY_FILES = 100;
+    private static final int ELEMENTARY_FILES_ITEM = 101;
+    private static final int SIM_RECORDS = 200;
+    private static final int SIM_RECORDS_ITEM = 201;
+    private static final int VALIDATE_NAME = 300;
+
+    static {
+        URI_MATCHER.addURI(SimPhonebookContract.AUTHORITY,
+                ElementaryFiles.ELEMENTARY_FILES_PATH_SEGMENT, ELEMENTARY_FILES);
+        URI_MATCHER.addURI(
+                SimPhonebookContract.AUTHORITY,
+                ElementaryFiles.ELEMENTARY_FILES_PATH_SEGMENT + "/"
+                        + SimPhonebookContract.SUBSCRIPTION_ID_PATH_SEGMENT + "/#/*",
+                ELEMENTARY_FILES_ITEM);
+        URI_MATCHER.addURI(SimPhonebookContract.AUTHORITY,
+                SimPhonebookContract.SUBSCRIPTION_ID_PATH_SEGMENT + "/#/*", SIM_RECORDS);
+        URI_MATCHER.addURI(SimPhonebookContract.AUTHORITY,
+                SimPhonebookContract.SUBSCRIPTION_ID_PATH_SEGMENT + "/#/*/#", SIM_RECORDS_ITEM);
+        URI_MATCHER.addURI(SimPhonebookContract.AUTHORITY,
+                SimPhonebookContract.SUBSCRIPTION_ID_PATH_SEGMENT + "/#/*/"
+                        + SimRecords.VALIDATE_NAME_PATH_SEGMENT,
+                VALIDATE_NAME);
+    }
+
+    // Only allow 1 write at a time to prevent races; the mutations are based on reads of the
+    // existing list of records which means concurrent writes would be problematic.
+    private final Lock mWriteLock = new ReentrantLock(true);
+    private SubscriptionManager mSubscriptionManager;
+    private Supplier<IIccPhoneBook> mIccPhoneBookSupplier;
+    private ContentNotifier mContentNotifier;
+
+    static int efIdForEfType(@ElementaryFiles.EfType int efType) {
+        switch (efType) {
+            case ElementaryFiles.EF_ADN:
+                return IccConstants.EF_ADN;
+            case ElementaryFiles.EF_FDN:
+                return IccConstants.EF_FDN;
+            case ElementaryFiles.EF_SDN:
+                return IccConstants.EF_SDN;
+            default:
+                return 0;
+        }
+    }
+
+    private static void validateProjection(Set<String> allowed, String[] projection) {
+        if (projection == null || allowed.containsAll(Arrays.asList(projection))) {
+            return;
+        }
+        Set<String> invalidColumns = new LinkedHashSet<>(Arrays.asList(projection));
+        invalidColumns.removeAll(allowed);
+        throw new IllegalArgumentException(
+                "Unsupported columns: " + Joiner.on(",").join(invalidColumns));
+    }
+
+    private static int getRecordSize(int[] recordsSize) {
+        return recordsSize[0];
+    }
+
+    private static int getRecordCount(int[] recordsSize) {
+        return recordsSize[2];
+    }
+
+    /** Returns the IccPhoneBook used to load the AdnRecords. */
+    private static IIccPhoneBook getIccPhoneBook() {
+        return IIccPhoneBook.Stub.asInterface(TelephonyFrameworkInitializer
+                .getTelephonyServiceManager().getIccPhoneBookServiceRegisterer().get());
+    }
+
+    @Override
+    public boolean onCreate() {
+        ContentResolver resolver = getContext().getContentResolver();
+        return onCreate(getContext().getSystemService(SubscriptionManager.class),
+                SimPhonebookProvider::getIccPhoneBook,
+                uri -> resolver.notifyChange(uri, null));
+    }
+
+    @TestApi
+    boolean onCreate(SubscriptionManager subscriptionManager,
+            Supplier<IIccPhoneBook> iccPhoneBookSupplier, ContentNotifier notifier) {
+        if (subscriptionManager == null) {
+            return false;
+        }
+        mSubscriptionManager = subscriptionManager;
+        mIccPhoneBookSupplier = iccPhoneBookSupplier;
+        mContentNotifier = notifier;
+
+        mSubscriptionManager.addOnSubscriptionsChangedListener(MoreExecutors.directExecutor(),
+                new SubscriptionManager.OnSubscriptionsChangedListener() {
+                    boolean mFirstCallback = true;
+                    private int[] mNotifiedSubIds = {};
+
+                    @Override
+                    public void onSubscriptionsChanged() {
+                        if (mFirstCallback) {
+                            mFirstCallback = false;
+                            return;
+                        }
+                        int[] activeSubIds = mSubscriptionManager.getActiveSubscriptionIdList();
+                        if (!Arrays.equals(mNotifiedSubIds, activeSubIds)) {
+                            notifier.notifyChange(SimPhonebookContract.AUTHORITY_URI);
+                            mNotifiedSubIds = Arrays.copyOf(activeSubIds, activeSubIds.length);
+                        }
+                    }
+                });
+        return true;
+    }
+
+
+    @Nullable
+    @Override
+    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable Bundle queryArgs,
+            @Nullable CancellationSignal cancellationSignal) {
+        if (queryArgs != null && (queryArgs.containsKey(ContentResolver.QUERY_ARG_SQL_SELECTION)
+                || queryArgs.containsKey(ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS)
+                || queryArgs.containsKey(ContentResolver.QUERY_ARG_SQL_LIMIT))) {
+            throw new IllegalArgumentException(
+                    "A SQL selection was provided but it is not supported by this provider.");
+        }
+        switch (URI_MATCHER.match(uri)) {
+            case ELEMENTARY_FILES:
+                return queryElementaryFiles(projection);
+            case ELEMENTARY_FILES_ITEM:
+                return queryElementaryFilesItem(PhonebookArgs.forElementaryFilesItem(uri),
+                        projection);
+            case SIM_RECORDS:
+                return querySimRecords(PhonebookArgs.forSimRecords(uri, queryArgs), projection);
+            case SIM_RECORDS_ITEM:
+                return querySimRecordsItem(PhonebookArgs.forSimRecordsItem(uri, queryArgs),
+                        projection);
+            case VALIDATE_NAME:
+                return queryValidateName(PhonebookArgs.forValidateName(uri, queryArgs), queryArgs);
+            default:
+                throw new IllegalArgumentException("Unsupported Uri " + uri);
+        }
+    }
+
+    @Nullable
+    @Override
+    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,
+            @Nullable String[] selectionArgs, @Nullable String sortOrder,
+            @Nullable CancellationSignal cancellationSignal) {
+        throw new UnsupportedOperationException("Only query with Bundle is supported");
+    }
+
+    @Nullable
+    @Override
+    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,
+            @Nullable String[] selectionArgs, @Nullable String sortOrder) {
+        throw new UnsupportedOperationException("Only query with Bundle is supported");
+    }
+
+    private Cursor queryElementaryFiles(String[] projection) {
+        validateProjection(ELEMENTARY_FILES_COLUMNS_SET, projection);
+        if (projection == null) {
+            projection = ELEMENTARY_FILES_ALL_COLUMNS;
+        }
+
+        MatrixCursor result = new MatrixCursor(projection);
+
+        List<SubscriptionInfo> activeSubscriptions = getActiveSubscriptionInfoList();
+        for (SubscriptionInfo subInfo : activeSubscriptions) {
+            try {
+                addEfToCursor(result, subInfo, ElementaryFiles.EF_ADN);
+                addEfToCursor(result, subInfo, ElementaryFiles.EF_FDN);
+                addEfToCursor(result, subInfo, ElementaryFiles.EF_SDN);
+            } catch (RemoteException e) {
+                // Return an empty cursor. If service to access it is throwing remote
+                // exceptions then it's basically the same as not having a SIM.
+                return new MatrixCursor(projection, 0);
+            }
+        }
+        return result;
+    }
+
+    private Cursor queryElementaryFilesItem(PhonebookArgs args, String[] projection) {
+        validateProjection(ELEMENTARY_FILES_COLUMNS_SET, projection);
+
+        MatrixCursor result = new MatrixCursor(projection);
+        try {
+            addEfToCursor(
+                    result, getActiveSubscriptionInfo(args.subscriptionId), args.efType);
+        } catch (RemoteException e) {
+            // Return an empty cursor. If service to access it is throwing remote
+            // exceptions then it's basically the same as not having a SIM.
+            return new MatrixCursor(projection, 0);
+        }
+        return result;
+    }
+
+    private void addEfToCursor(MatrixCursor result, SubscriptionInfo subscriptionInfo,
+            int efType) throws RemoteException {
+        int[] recordsSize = mIccPhoneBookSupplier.get().getAdnRecordsSizeForSubscriber(
+                subscriptionInfo.getSubscriptionId(), efIdForEfType(efType));
+        addEfToCursor(result, subscriptionInfo, efType, recordsSize);
+    }
+
+    private void addEfToCursor(MatrixCursor result, SubscriptionInfo subscriptionInfo,
+            int efType, int[] recordsSize) throws RemoteException {
+        // If the record count is zero then the SIM doesn't support the elementary file so just
+        // omit it.
+        if (recordsSize == null || getRecordCount(recordsSize) == 0) {
+            return;
+        }
+        MatrixCursor.RowBuilder row = result.newRow()
+                .add(ElementaryFiles.SLOT_INDEX, subscriptionInfo.getSimSlotIndex())
+                .add(ElementaryFiles.SUBSCRIPTION_ID, subscriptionInfo.getSubscriptionId())
+                .add(ElementaryFiles.EF_TYPE, efType)
+                .add(ElementaryFiles.MAX_RECORDS, getRecordCount(recordsSize))
+                .add(ElementaryFiles.NAME_MAX_LENGTH,
+                        AdnRecord.getMaxAlphaTagBytes(getRecordSize(recordsSize)))
+                .add(ElementaryFiles.PHONE_NUMBER_MAX_LENGTH,
+                        AdnRecord.getMaxPhoneNumberDigits());
+        if (result.getColumnIndex(ElementaryFiles.RECORD_COUNT) != -1) {
+            int efid = efIdForEfType(efType);
+            List<AdnRecord> existingRecords = mIccPhoneBookSupplier.get()
+                    .getAdnRecordsInEfForSubscriber(subscriptionInfo.getSubscriptionId(), efid);
+            int nonEmptyCount = 0;
+            for (AdnRecord record : existingRecords) {
+                if (!record.isEmpty()) {
+                    nonEmptyCount++;
+                }
+            }
+            row.add(ElementaryFiles.RECORD_COUNT, nonEmptyCount);
+        }
+    }
+
+    private Cursor querySimRecords(PhonebookArgs args, String[] projection) {
+        validateSubscriptionAndEf(args);
+        if (projection == null) {
+            projection = SIM_RECORDS_ALL_COLUMNS;
+        }
+
+        List<AdnRecord> records = loadRecordsForEf(args);
+        if (records == null) {
+            return new MatrixCursor(projection, 0);
+        }
+        MatrixCursor result = new MatrixCursor(projection, records.size());
+        List<Pair<AdnRecord, MatrixCursor.RowBuilder>> rowBuilders = new ArrayList<>(
+                records.size());
+        for (AdnRecord record : records) {
+            if (!record.isEmpty()) {
+                rowBuilders.add(Pair.create(record, result.newRow()));
+            }
+        }
+        // This is kind of ugly but avoids looking up columns in an inner loop.
+        for (String column : projection) {
+            switch (column) {
+                case SimRecords.SUBSCRIPTION_ID:
+                    for (Pair<AdnRecord, MatrixCursor.RowBuilder> row : rowBuilders) {
+                        row.second.add(args.subscriptionId);
+                    }
+                    break;
+                case SimRecords.ELEMENTARY_FILE_TYPE:
+                    for (Pair<AdnRecord, MatrixCursor.RowBuilder> row : rowBuilders) {
+                        row.second.add(args.efType);
+                    }
+                    break;
+                case SimRecords.RECORD_NUMBER:
+                    for (Pair<AdnRecord, MatrixCursor.RowBuilder> row : rowBuilders) {
+                        row.second.add(row.first.getRecId());
+                    }
+                    break;
+                case SimRecords.NAME:
+                    for (Pair<AdnRecord, MatrixCursor.RowBuilder> row : rowBuilders) {
+                        row.second.add(row.first.getAlphaTag());
+                    }
+                    break;
+                case SimRecords.PHONE_NUMBER:
+                    for (Pair<AdnRecord, MatrixCursor.RowBuilder> row : rowBuilders) {
+                        row.second.add(row.first.getNumber());
+                    }
+                    break;
+                default:
+                    Rlog.w(TAG, "Column " + column + " is unsupported for " + args.uri);
+                    break;
+            }
+        }
+        return result;
+    }
+
+    private Cursor querySimRecordsItem(PhonebookArgs args, String[] projection) {
+        if (projection == null) {
+            projection = SIM_RECORDS_ALL_COLUMNS;
+        }
+        validateSubscriptionAndEf(args);
+        AdnRecord record = loadRecord(args);
+
+        MatrixCursor result = new MatrixCursor(projection, 1);
+        if (record == null || record.isEmpty()) {
+            return result;
+        }
+        result.newRow()
+                .add(SimRecords.SUBSCRIPTION_ID, args.subscriptionId)
+                .add(SimRecords.ELEMENTARY_FILE_TYPE, args.efType)
+                .add(SimRecords.RECORD_NUMBER, record.getRecId())
+                .add(SimRecords.NAME, record.getAlphaTag())
+                .add(SimRecords.PHONE_NUMBER, record.getNumber());
+        return result;
+    }
+
+    private Cursor queryValidateName(PhonebookArgs args, @Nullable Bundle queryArgs) {
+        if (queryArgs == null) {
+            throw new IllegalArgumentException(SimRecords.NAME + " is required.");
+        }
+        validateSubscriptionAndEf(args);
+        String name = queryArgs.getString(SimRecords.NAME);
+
+        // Cursor extras are used to return the result.
+        Cursor result = new MatrixCursor(new String[0], 0);
+        Bundle extras = new Bundle();
+        extras.putParcelable(SimRecords.EXTRA_NAME_VALIDATION_RESULT, validateName(args, name));
+        result.setExtras(extras);
+        return result;
+    }
+
+    @Nullable
+    @Override
+    public String getType(@NonNull Uri uri) {
+        switch (URI_MATCHER.match(uri)) {
+            case ELEMENTARY_FILES:
+                return ElementaryFiles.CONTENT_TYPE;
+            case ELEMENTARY_FILES_ITEM:
+                return ElementaryFiles.CONTENT_ITEM_TYPE;
+            case SIM_RECORDS:
+                return SimRecords.CONTENT_TYPE;
+            case SIM_RECORDS_ITEM:
+                return SimRecords.CONTENT_ITEM_TYPE;
+            default:
+                throw new IllegalArgumentException("Unsupported Uri " + uri);
+        }
+    }
+
+    @Nullable
+    @Override
+    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
+        return insert(uri, values, null);
+    }
+
+    @Nullable
+    @Override
+    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values, @Nullable Bundle extras) {
+        switch (URI_MATCHER.match(uri)) {
+            case SIM_RECORDS:
+                return insertSimRecord(PhonebookArgs.forSimRecords(uri, extras), values);
+            case ELEMENTARY_FILES:
+            case ELEMENTARY_FILES_ITEM:
+            case SIM_RECORDS_ITEM:
+                throw new UnsupportedOperationException(uri + " does not support insert");
+            default:
+                throw new IllegalArgumentException("Unsupported Uri " + uri);
+        }
+    }
+
+    private Uri insertSimRecord(PhonebookArgs args, ContentValues values) {
+        validateWritableEf(args, "insert");
+        validateSubscriptionAndEf(args);
+
+        if (values == null || values.isEmpty()) {
+            return null;
+        }
+        validateValues(args, values);
+        String newName = Strings.nullToEmpty(values.getAsString(SimRecords.NAME));
+        String newPhoneNumber = Strings.nullToEmpty(values.getAsString(SimRecords.PHONE_NUMBER));
+
+        acquireWriteLockOrThrow();
+        try {
+            List<AdnRecord> records = loadRecordsForEf(args);
+            if (records == null) {
+                Rlog.e(TAG, "Failed to load existing records for " + args.uri);
+                return null;
+            }
+            AdnRecord emptyRecord = null;
+            for (AdnRecord record : records) {
+                if (record.isEmpty()) {
+                    emptyRecord = record;
+                    break;
+                }
+            }
+            if (emptyRecord == null) {
+                // When there are no empty records that means the EF is full.
+                throw new IllegalStateException(
+                        args.uri + " is full. Please delete records to add new ones.");
+            }
+            boolean success = updateRecord(args, emptyRecord, args.pin2, newName, newPhoneNumber);
+            if (!success) {
+                Rlog.e(TAG, "Insert failed for " + args.uri);
+                // Something didn't work but since we don't have any more specific
+                // information to provide to the caller it's better to just return null
+                // rather than throwing and possibly crashing their process.
+                return null;
+            }
+            notifyChange();
+            return SimRecords.getItemUri(args.subscriptionId, args.efType, emptyRecord.getRecId());
+        } finally {
+            releaseWriteLock();
+        }
+    }
+
+    @Override
+    public int delete(@NonNull Uri uri, @Nullable String selection,
+            @Nullable String[] selectionArgs) {
+        throw new UnsupportedOperationException("Only delete with Bundle is supported");
+    }
+
+    @Override
+    public int delete(@NonNull Uri uri, @Nullable Bundle extras) {
+        switch (URI_MATCHER.match(uri)) {
+            case SIM_RECORDS_ITEM:
+                return deleteSimRecordsItem(PhonebookArgs.forSimRecordsItem(uri, extras));
+            case ELEMENTARY_FILES:
+            case ELEMENTARY_FILES_ITEM:
+            case SIM_RECORDS:
+                throw new UnsupportedOperationException(uri + " does not support delete");
+            default:
+                throw new IllegalArgumentException("Unsupported Uri " + uri);
+        }
+    }
+
+    private int deleteSimRecordsItem(PhonebookArgs args) {
+        validateWritableEf(args, "delete");
+        validateSubscriptionAndEf(args);
+
+        acquireWriteLockOrThrow();
+        try {
+            AdnRecord record = loadRecord(args);
+            if (record == null || record.isEmpty()) {
+                return 0;
+            }
+            if (!updateRecord(args, record, args.pin2, "", "")) {
+                Rlog.e(TAG, "Failed to delete " + args.uri);
+            }
+            notifyChange();
+        } finally {
+            releaseWriteLock();
+        }
+        return 1;
+    }
+
+
+    @Override
+    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable Bundle extras) {
+        switch (URI_MATCHER.match(uri)) {
+            case SIM_RECORDS_ITEM:
+                return updateSimRecordsItem(PhonebookArgs.forSimRecordsItem(uri, extras), values);
+            case ELEMENTARY_FILES:
+            case ELEMENTARY_FILES_ITEM:
+            case SIM_RECORDS:
+                throw new UnsupportedOperationException(uri + " does not support update");
+            default:
+                throw new IllegalArgumentException("Unsupported Uri " + uri);
+        }
+    }
+
+    @Override
+    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection,
+            @Nullable String[] selectionArgs) {
+        throw new UnsupportedOperationException("Only Update with bundle is supported");
+    }
+
+    private int updateSimRecordsItem(PhonebookArgs args, ContentValues values) {
+        validateWritableEf(args, "update");
+        validateSubscriptionAndEf(args);
+
+        if (values == null || values.isEmpty()) {
+            return 0;
+        }
+        validateValues(args, values);
+        String newName = Strings.nullToEmpty(values.getAsString(SimRecords.NAME));
+        String newPhoneNumber = Strings.nullToEmpty(values.getAsString(SimRecords.PHONE_NUMBER));
+
+        acquireWriteLockOrThrow();
+
+        try {
+            AdnRecord record = loadRecord(args);
+
+            // Note we allow empty records to be updated. This is a bit weird because they are
+            // not returned by query methods but this allows a client application assign a name
+            // to a specific record number. This may be desirable in some phone app use cases since
+            // the record number is often used as a quick dial index.
+            if (record == null) {
+                return 0;
+            }
+            if (!updateRecord(args, record, args.pin2, newName, newPhoneNumber)) {
+                Rlog.e(TAG, "Failed to update " + args.uri);
+                return 0;
+            }
+            notifyChange();
+        } finally {
+            releaseWriteLock();
+        }
+        return 1;
+    }
+
+    void validateSubscriptionAndEf(PhonebookArgs args) {
+        SubscriptionInfo info =
+                args.subscriptionId != SubscriptionManager.INVALID_SUBSCRIPTION_ID
+                        ? getActiveSubscriptionInfo(args.subscriptionId)
+                        : null;
+        if (info == null) {
+            throw new IllegalArgumentException("No active SIM with subscription ID "
+                    + args.subscriptionId);
+        }
+
+        int[] recordsSize = getRecordsSizeForEf(args);
+        if (recordsSize == null || recordsSize[1] == 0) {
+            throw new IllegalArgumentException(args.efName
+                    + " is not supported for SIM with subscription ID " + args.subscriptionId);
+        }
+    }
+
+    private void acquireWriteLockOrThrow() {
+        try {
+            if (!mWriteLock.tryLock(WRITE_TIMEOUT_SECONDS, TimeUnit.SECONDS)) {
+                throw new IllegalStateException("Timeout waiting to write");
+            }
+        } catch (InterruptedException e) {
+            throw new IllegalStateException("Write failed");
+        }
+    }
+
+    private void releaseWriteLock() {
+        mWriteLock.unlock();
+    }
+
+    private void validateWritableEf(PhonebookArgs args, String operationName) {
+        if (args.efType == ElementaryFiles.EF_FDN) {
+            if (hasPermissionsForFdnWrite(args)) {
+                return;
+            }
+        }
+        if (args.efType != ElementaryFiles.EF_ADN) {
+            throw new UnsupportedOperationException(
+                    args.uri + " does not support " + operationName);
+        }
+    }
+
+    private boolean hasPermissionsForFdnWrite(PhonebookArgs args) {
+        TelephonyManager telephonyManager = getContext().getSystemService(
+                TelephonyManager.class);
+        String callingPackage = getCallingPackage();
+        int granted = PackageManager.PERMISSION_DENIED;
+        if (callingPackage != null) {
+            granted = getContext().getPackageManager().checkPermission(
+                    Manifest.permission.MODIFY_PHONE_STATE, callingPackage);
+        }
+        return granted == PackageManager.PERMISSION_GRANTED
+                || telephonyManager.hasCarrierPrivileges(args.subscriptionId);
+
+    }
+
+
+    private boolean updateRecord(PhonebookArgs args, AdnRecord existingRecord, String pin2,
+            String newName, String newPhone) {
+        try {
+            return mIccPhoneBookSupplier.get().updateAdnRecordsInEfByIndexForSubscriber(
+                    args.subscriptionId, existingRecord.getEfid(), newName, newPhone,
+                    existingRecord.getRecId(),
+                    pin2);
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    private SimRecords.NameValidationResult validateName(
+            PhonebookArgs args, @Nullable String name) {
+        name = Strings.nullToEmpty(name);
+        int recordSize = getRecordSize(getRecordsSizeForEf(args));
+        // Validating the name consists of encoding the record in the binary format that it is
+        // stored on the SIM then decoding it and checking whether the decoded name is the same.
+        // The AOSP implementation of AdnRecord replaces unsupported characters with spaces during
+        // encoding.
+        // TODO: It would be good to update AdnRecord to support UCS-2 on the encode path (it
+        //  supports it on the decode path). Right now it's not supported and so any non-latin
+        //  characters will not be valid (at least in the AOSP implementation).
+        byte[] encodedName = AdnRecord.encodeAlphaTag(name);
+        String sanitizedName = AdnRecord.decodeAlphaTag(encodedName, 0, encodedName.length);
+        return new SimRecords.NameValidationResult(name, sanitizedName,
+                encodedName.length, AdnRecord.getMaxAlphaTagBytes(recordSize));
+    }
+
+    private void validatePhoneNumber(@Nullable String phoneNumber) {
+        if (phoneNumber == null || phoneNumber.isEmpty()) {
+            throw new IllegalArgumentException(SimRecords.PHONE_NUMBER + " is required.");
+        }
+        int actualLength = phoneNumber.length();
+        // When encoded the "+" prefix sets a bit and so doesn't count against the maximum length
+        if (phoneNumber.startsWith("+")) {
+            actualLength--;
+        }
+        if (actualLength > AdnRecord.getMaxPhoneNumberDigits()) {
+            throw new IllegalArgumentException(SimRecords.PHONE_NUMBER + " is too long.");
+        }
+        for (int i = 0; i < phoneNumber.length(); i++) {
+            char c = phoneNumber.charAt(i);
+            if (!PhoneNumberUtils.isNonSeparator(c)) {
+                throw new IllegalArgumentException(
+                        SimRecords.PHONE_NUMBER + " contains unsupported characters.");
+            }
+        }
+    }
+
+    private void validateValues(PhonebookArgs args, ContentValues values) {
+        if (!SIM_RECORDS_WRITABLE_COLUMNS.containsAll(values.keySet())) {
+            Set<String> unsupportedColumns = new ArraySet<>(values.keySet());
+            unsupportedColumns.removeAll(SIM_RECORDS_WRITABLE_COLUMNS);
+            throw new IllegalArgumentException("Unsupported columns: " + Joiner.on(',')
+                    .join(unsupportedColumns));
+        }
+
+        String phoneNumber = values.getAsString(SimRecords.PHONE_NUMBER);
+        validatePhoneNumber(phoneNumber);
+
+        String name = values.getAsString(SimRecords.NAME);
+        SimRecords.NameValidationResult result = validateName(args, name);
+
+        if (result.getEncodedLength() > result.getMaxEncodedLength()) {
+            throw new IllegalArgumentException(SimRecords.NAME + " is too long.");
+        } else if (!Objects.equals(result.getName(), result.getSanitizedName())) {
+            throw new IllegalArgumentException(
+                    SimRecords.NAME + " contains unsupported characters.");
+        }
+    }
+
+    private List<SubscriptionInfo> getActiveSubscriptionInfoList() {
+        // Getting the SubscriptionInfo requires READ_PHONE_STATE but we're only returning
+        // the subscription ID and slot index which are not sensitive information.
+        CallingIdentity identity = clearCallingIdentity();
+        try {
+            return mSubscriptionManager.getActiveSubscriptionInfoList();
+        } finally {
+            restoreCallingIdentity(identity);
+        }
+    }
+
+    private SubscriptionInfo getActiveSubscriptionInfo(int subId) {
+        // Getting the SubscriptionInfo requires READ_PHONE_STATE.
+        CallingIdentity identity = clearCallingIdentity();
+        try {
+            return mSubscriptionManager.getActiveSubscriptionInfo(subId);
+        } finally {
+            restoreCallingIdentity(identity);
+        }
+    }
+
+    private List<AdnRecord> loadRecordsForEf(PhonebookArgs args) {
+        try {
+            return mIccPhoneBookSupplier.get().getAdnRecordsInEfForSubscriber(
+                    args.subscriptionId, args.efid);
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    private AdnRecord loadRecord(PhonebookArgs args) {
+        List<AdnRecord> records = loadRecordsForEf(args);
+        if (args.recordNumber > records.size()) {
+            return null;
+        }
+        AdnRecord result = records.get(args.recordNumber - 1);
+        // This should be true but the service could have a different implementation.
+        if (result.getRecId() == args.recordNumber) {
+            return result;
+        }
+        for (AdnRecord record : records) {
+            if (record.getRecId() == args.recordNumber) {
+                return result;
+            }
+        }
+        return null;
+    }
+
+
+    private int[] getRecordsSizeForEf(PhonebookArgs args) {
+        try {
+            return mIccPhoneBookSupplier.get().getAdnRecordsSizeForSubscriber(
+                    args.subscriptionId, args.efid);
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    void notifyChange() {
+        mContentNotifier.notifyChange(SimPhonebookContract.AUTHORITY_URI);
+    }
+
+    /** Testable wrapper around {@link ContentResolver#notifyChange(Uri, ContentObserver)} */
+    @TestApi
+    interface ContentNotifier {
+        void notifyChange(Uri uri);
+    }
+
+    /**
+     * Holds the arguments extracted from the Uri and query args for accessing the referenced
+     * phonebook data on a SIM.
+     */
+    private static class PhonebookArgs {
+        public final Uri uri;
+        public final int subscriptionId;
+        public final String efName;
+        public final int efType;
+        public final int efid;
+        public final int recordNumber;
+        public final String pin2;
+
+        PhonebookArgs(Uri uri, int subscriptionId, String efName,
+                @ElementaryFiles.EfType int efType, int efid, int recordNumber,
+                @Nullable Bundle queryArgs) {
+            this.uri = uri;
+            this.subscriptionId = subscriptionId;
+            this.efName = efName;
+            this.efType = efType;
+            this.efid = efid;
+            this.recordNumber = recordNumber;
+            pin2 = efType == ElementaryFiles.EF_FDN && queryArgs != null
+                    ? queryArgs.getString(SimRecords.QUERY_ARG_PIN2)
+                    : null;
+        }
+
+        static PhonebookArgs createFromEfName(Uri uri, int subscriptionId,
+                String efName, int recordNumber, @Nullable Bundle queryArgs) {
+            int efType;
+            int efid;
+            if (efName != null) {
+                switch (efName) {
+                    case ElementaryFiles.EF_ADN_PATH_SEGMENT:
+                        efType = ElementaryFiles.EF_ADN;
+                        efid = IccConstants.EF_ADN;
+                        break;
+                    case ElementaryFiles.EF_FDN_PATH_SEGMENT:
+                        efType = ElementaryFiles.EF_FDN;
+                        efid = IccConstants.EF_FDN;
+                        break;
+                    case ElementaryFiles.EF_SDN_PATH_SEGMENT:
+                        efType = ElementaryFiles.EF_SDN;
+                        efid = IccConstants.EF_SDN;
+                        break;
+                    default:
+                        throw new IllegalArgumentException(
+                                "Unrecognized elementary file " + efName);
+                }
+            } else {
+                efType = ElementaryFiles.EF_UNKNOWN;
+                efid = 0;
+            }
+            return new PhonebookArgs(uri, subscriptionId, efName, efType, efid, recordNumber,
+                    queryArgs);
+        }
+
+        /**
+         * Pattern: elementary_files/subid/${subscriptionId}/${efName}
+         *
+         * e.g. elementary_files/subid/1/adn
+         *
+         * @see ElementaryFiles#getItemUri(int, int)
+         * @see #ELEMENTARY_FILES_ITEM
+         */
+        static PhonebookArgs forElementaryFilesItem(Uri uri) {
+            int subscriptionId = parseSubscriptionIdFromUri(uri, 2);
+            String efName = uri.getPathSegments().get(3);
+            return PhonebookArgs.createFromEfName(
+                    uri, subscriptionId, efName, -1, null);
+        }
+
+        /**
+         * Pattern: subid/${subscriptionId}/${efName}
+         *
+         * <p>e.g. subid/1/adn
+         *
+         * @see SimRecords#getContentUri(int, int)
+         * @see #SIM_RECORDS
+         */
+        static PhonebookArgs forSimRecords(Uri uri, Bundle queryArgs) {
+            int subscriptionId = parseSubscriptionIdFromUri(uri, 1);
+            String efName = uri.getPathSegments().get(2);
+            return PhonebookArgs.createFromEfName(uri, subscriptionId, efName, -1, queryArgs);
+        }
+
+        /**
+         * Pattern: subid/${subscriptionId}/${efName}/${recordNumber}
+         *
+         * <p>e.g. subid/1/adn/10
+         *
+         * @see SimRecords#getItemUri(int, int, int)
+         * @see #SIM_RECORDS_ITEM
+         */
+        static PhonebookArgs forSimRecordsItem(Uri uri, Bundle queryArgs) {
+            int subscriptionId = parseSubscriptionIdFromUri(uri, 1);
+            String efName = uri.getPathSegments().get(2);
+            int recordNumber = parseRecordNumberFromUri(uri, 3);
+            return PhonebookArgs.createFromEfName(uri, subscriptionId, efName, recordNumber,
+                    queryArgs);
+        }
+
+        /**
+         * Pattern: subid/${subscriptionId}/${efName}/validate_name
+         *
+         * @see SimRecords#validateName(ContentResolver, int, int, String)
+         * @see #VALIDATE_NAME
+         */
+        static PhonebookArgs forValidateName(Uri uri, Bundle queryArgs) {
+            int subscriptionId = parseSubscriptionIdFromUri(uri, 1);
+            String efName = uri.getPathSegments().get(2);
+            return PhonebookArgs.createFromEfName(
+                    uri, subscriptionId, efName, -1, queryArgs);
+        }
+
+        private static int parseSubscriptionIdFromUri(Uri uri, int pathIndex) {
+            if (pathIndex == -1) {
+                return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+            }
+            String segment = uri.getPathSegments().get(pathIndex);
+            try {
+                return Integer.parseInt(segment);
+            } catch (NumberFormatException e) {
+                throw new IllegalArgumentException("Invalid subscription ID: " + segment);
+            }
+        }
+
+        private static int parseRecordNumberFromUri(Uri uri, int pathIndex) {
+            try {
+                return Integer.parseInt(uri.getPathSegments().get(pathIndex));
+            } catch (NumberFormatException e) {
+                throw new IllegalArgumentException(
+                        "Invalid record index: " + uri.getLastPathSegment());
+            }
+        }
+    }
+}
