[automerger skipped] Merge Coral/Flame into AOSP master am: 5de450023f -s ours am: bbd3513db0 -s ours am: 03a210e8c3 -s ours
am: f2461ab96d -s ours
am skip reason: change_id I9fc77bfb2ee9c2a7567dc3645cf8cf436388e975 with SHA1 2a16dc6aa2 is in history

Change-Id: Ibb45f1a8b4589954f5ec004f1ab80b95d95c113c
diff --git a/Android.bp b/Android.bp
index eabd567..ad23fcd 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,7 +1,13 @@
+filegroup {
+    name: "jarjar-rules",
+    srcs: ["jarjar-rules.txt"],
+}
+
 android_app {
     name: "TelephonyProvider",
     privileged: true,
     srcs: ["src/**/*.java"],
+    jarjar_rules: ":jarjar-rules",
     platform_apis: true,
     certificate: "platform",
     libs: ["telephony-common"],
diff --git a/jarjar-rules.txt b/jarjar-rules.txt
new file mode 100644
index 0000000..b0d73d3
--- /dev/null
+++ b/jarjar-rules.txt
@@ -0,0 +1 @@
+rule com.android.internal.util.XmlUtils* com.android.internal.telephony.XmlUtils@1
diff --git a/src/com/android/providers/telephony/CarrierIdProvider.java b/src/com/android/providers/telephony/CarrierIdProvider.java
index 44f053d..d43e6c6 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.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 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;
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 4add85d..034efaa 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.android.internal.telephony.PhoneFactory;
@@ -267,7 +266,7 @@
 
     /**
      * The primary purpose of this DatabaseErrorHandler is to broadcast an intent on corruption and
-     * print a Slog.wtf so database corruption can be caught earlier.
+     * print a Log.wtf so database corruption can be caught earlier.
      */
     private static class MmsSmsDatabaseErrorHandler implements DatabaseErrorHandler {
         private DefaultDatabaseErrorHandler mDefaultDatabaseErrorHandler
@@ -571,7 +570,7 @@
     }
 
     private static void localLogWtf(String logMsg) {
-        Slog.wtf(TAG, logMsg);
+        Log.wtf(TAG, logMsg);
         PhoneFactory.localLog(TAG, logMsg);
     }
 
diff --git a/src/com/android/providers/telephony/SqlTokenFinder.java b/src/com/android/providers/telephony/SqlTokenFinder.java
deleted file mode 100644
index 9be49fe..0000000
--- a/src/com/android/providers/telephony/SqlTokenFinder.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-package com.android.providers.telephony;
-
-import android.annotation.Nullable;
-
-import java.util.function.Consumer;
-
-/**
- * Simple SQL parser to check statements for usage of prohibited/sensitive fields. Mostly copied
- * from
- * packages/providers/ContactsProvider/src/com/android/providers/contacts/sqlite/SqlChecker.java
- */
-public class SqlTokenFinder{
-    private static boolean isAlpha(char ch) {
-        return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || (ch == '_');
-    }
-
-    private static boolean isNum(char ch) {
-        return ('0' <= ch && ch <= '9');
-    }
-
-    private static boolean isAlNum(char ch) {
-        return isAlpha(ch) || isNum(ch);
-    }
-
-    private static boolean isAnyOf(char ch, String set) {
-        return set.indexOf(ch) >= 0;
-    }
-
-    private static char peek(String s, int index) {
-        return index < s.length() ? s.charAt(index) : '\0';
-    }
-
-    /**
-     * SQL Tokenizer specialized to extract tokens from SQL (snippets).
-     *
-     * Based on sqlite3GetToken() in tokenzie.c in SQLite.
-     *
-     * Source for v3.8.6 (which android uses): http://www.sqlite.org/src/artifact/ae45399d6252b4d7
-     * (Latest source as of now: http://www.sqlite.org/src/artifact/78c8085bc7af1922)
-     *
-     * Also draft spec: http://www.sqlite.org/draft/tokenreq.html
-     */
-    public static void findTokens(@Nullable String sql, Consumer<String> checker) {
-        if (sql == null) {
-            return;
-        }
-        int pos = 0;
-        final int len = sql.length();
-        while (pos < len) {
-            final char ch = peek(sql, pos);
-
-            // Regular token.
-            if (isAlpha(ch)) {
-                final int start = pos;
-                pos++;
-                while (isAlNum(peek(sql, pos))) {
-                    pos++;
-                }
-                final int end = pos;
-
-                final String token = sql.substring(start, end);
-                checker.accept(token);
-
-                continue;
-            }
-
-            // Handle quoted tokens
-            if (isAnyOf(ch, "'\"`")) {
-                final int quoteStart = pos;
-                pos++;
-
-                for (;;) {
-                    pos = sql.indexOf(ch, pos);
-                    if (pos < 0) {
-                        throw new IllegalArgumentException("Unterminated quote in" + sql);
-                    }
-                    if (peek(sql, pos + 1) != ch) {
-                        break;
-                    }
-                    // Quoted quote char -- e.g. "abc""def" is a single string.
-                    pos += 2;
-                }
-                final int quoteEnd = pos;
-                pos++;
-
-                if (ch != '\'') {
-                    // Extract the token
-                    final String tokenUnquoted = sql.substring(quoteStart + 1, quoteEnd);
-
-                    final String token;
-
-                    // Unquote if needed. i.e. "aa""bb" -> aa"bb
-                    if (tokenUnquoted.indexOf(ch) >= 0) {
-                        token = tokenUnquoted.replaceAll(
-                                String.valueOf(ch) + ch, String.valueOf(ch));
-                    } else {
-                        token = tokenUnquoted;
-                    }
-                    checker.accept(token);
-                }
-                continue;
-            }
-            // Handle tokens enclosed in [...]
-            if (ch == '[') {
-                final int quoteStart = pos;
-                pos++;
-
-                pos = sql.indexOf(']', pos);
-                if (pos < 0) {
-                    throw new IllegalArgumentException("Unterminated quote in" + sql);
-                }
-                final int quoteEnd = pos;
-                pos++;
-
-                final String token = sql.substring(quoteStart + 1, quoteEnd);
-
-                checker.accept(token);
-                continue;
-            }
-
-            // Detect comments.
-            if (ch == '-' && peek(sql, pos + 1) == '-') {
-                pos += 2;
-                pos = sql.indexOf('\n', pos);
-                if (pos < 0) {
-                    // We disallow strings ending in an inline comment.
-                    throw new IllegalArgumentException("Unterminated comment in" + sql);
-                }
-                pos++;
-
-                continue;
-            }
-            if (ch == '/' && peek(sql, pos + 1) == '*') {
-                pos += 2;
-                pos = sql.indexOf("*/", pos);
-                if (pos < 0) {
-                    throw new IllegalArgumentException("Unterminated comment in" + sql);
-                }
-                pos += 2;
-
-                continue;
-            }
-
-            // Semicolon is never allowed.
-            if (ch == ';') {
-                throw new IllegalArgumentException("Semicolon is not allowed in " + sql);
-            }
-
-            // For this purpose, we can simply ignore other characters.
-            // (Note it doesn't handle the X'' literal properly and reports this X as a token,
-            // but that should be fine...)
-            pos++;
-        }
-    }
-}
diff --git a/src/com/android/providers/telephony/TelephonyProvider.java b/src/com/android/providers/telephony/TelephonyProvider.java
index 56e9c8b..359ff50 100644
--- a/src/com/android/providers/telephony/TelephonyProvider.java
+++ b/src/com/android/providers/telephony/TelephonyProvider.java
@@ -93,7 +93,6 @@
 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;
@@ -101,31 +100,30 @@
 import android.os.UserHandle;
 import android.provider.Telephony;
 import android.telephony.ServiceState;
-import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.telephony.data.ApnSetting;
 import android.text.TextUtils;
-import android.util.EventLog;
 import android.util.Log;
 import android.util.Pair;
 import android.util.Xml;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.telephony.IApnSourceService;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.PhoneFactory;
 import com.android.internal.telephony.dataconnection.ApnSettingUtils;
 import com.android.internal.telephony.uicc.IccRecords;
 import com.android.internal.telephony.uicc.UiccController;
 import com.android.internal.util.XmlUtils;
+import android.service.carrier.IApnSourceService;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
+import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileReader;
 import java.io.IOException;
@@ -138,6 +136,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
@@ -207,10 +206,6 @@
     private static final String DEFAULT_PROTOCOL = "IP";
     private static final String DEFAULT_ROAMING_PROTOCOL = "IP";
 
-    // Used to check if certain queries contain subqueries that may attempt to access sensitive
-    // fields in the carriers db.
-    private static final String SQL_SELECT_TOKEN = "select";
-
     private static final UriMatcher s_urlMatcher = new UriMatcher(UriMatcher.NO_MATCH);
 
     private static final ContentValues s_currentNullMap;
@@ -589,10 +584,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) {
@@ -604,14 +607,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 {
@@ -2807,7 +2810,7 @@
         List<String> constraints = new ArrayList<String>();
 
         int match = s_urlMatcher.match(url);
-        checkQueryPermission(match, projectionIn, selection, sort);
+        checkPermission();
         switch (match) {
             case URL_TELEPHONY_USING_SUBID: {
                 subIdString = url.getLastPathSegment();
@@ -3016,69 +3019,6 @@
         return ret;
     }
 
-    private void checkQueryPermission(int match, String[] projectionIn, String selection,
-            String sort) {
-        // Determine if we need to do a check for fields in the selection
-        boolean selectionOrSortContainsSensitiveFields;
-        try {
-            selectionOrSortContainsSensitiveFields = containsSensitiveFields(selection);
-            selectionOrSortContainsSensitiveFields |= containsSensitiveFields(sort);
-        } catch (IllegalArgumentException e) {
-            // Malformed sql, check permission anyway and return.
-            checkPermission();
-            return;
-        }
-
-        if (selectionOrSortContainsSensitiveFields) {
-            try {
-                checkPermission();
-            } catch (SecurityException e) {
-                EventLog.writeEvent(0x534e4554, "124107808", Binder.getCallingUid());
-                throw e;
-            }
-        }
-
-        if (match != URL_SIMINFO && match != URL_SIMINFO_USING_SUBID) {
-            if (projectionIn != null) {
-                for (String column : projectionIn) {
-                    if (TYPE.equals(column) ||
-                            MMSC.equals(column) ||
-                            MMSPROXY.equals(column) ||
-                            MMSPORT.equals(column) ||
-                            MVNO_TYPE.equals(column) ||
-                            MVNO_MATCH_DATA.equals(column) ||
-                            APN.equals(column)) {
-                    } else {
-                        checkPermission();
-                        break;
-                    }
-                }
-            } else {
-                // null returns all columns, so need permission check
-                checkPermission();
-            }
-        } else {
-            // if querying siminfo, caller should have read privilege permissions
-            checkPhonePrivilegePermission();
-        }
-    }
-
-    private boolean containsSensitiveFields(String sqlStatement) {
-        try {
-            SqlTokenFinder.findTokens(sqlStatement, s -> {
-                switch (s.toLowerCase()) {
-                    case USER:
-                    case PASSWORD:
-                    case SQL_SELECT_TOKEN:
-                        throw new SecurityException();
-                }
-            });
-        } catch (SecurityException e) {
-            return true;
-        }
-        return false;
-    }
-
     /**
      * To find the current sim APN. Query APN based on {MCC, MNC, MVNO} to support backward
      * compatibility but will move to carrier id in the future.
@@ -3847,15 +3787,6 @@
         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;
-        }
-        throw new SecurityException("No phone privilege permission");
-    }
-
     private DatabaseHelper mOpenHelper;
 
     private void restoreDefaultAPN(int subId) {