Merge pi-dr1-dev to aosp-master am: a7712d7cd7 am: 34a4f7a103
am: a7eecb5f79

Change-Id: I8a23af1edfef203650a4b164175f3a13a0257878
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 31e5364..2b4c6f8 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -66,6 +66,13 @@
                   android:singleUser="true"
                   android:readPermission="android.permission.READ_SMS" />
 
+        <provider android:name="SmsChangesProvider"
+                  android:authorities="sms-changes"
+                  android:multiprocess="false"
+                  android:exported="true"
+                  android:singleUser="true"
+                  android:readPermission="android.permission.READ_SMS" />
+
         <!-- This is a singleton provider that is used by all users.
              A new instance is not created for each user. And the db is shared
              as well.
diff --git a/res/values-as/config.xml b/res/values-as/config.xml
new file mode 100644
index 0000000..99877a6
--- /dev/null
+++ b/res/values-as/config.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="persist_apns_for_plmn">
+    <item msgid="6413072509259000954">"20404"</item>
+    <item msgid="5639159280778239123">"310004"</item>
+    <item msgid="3860605521380788028">"310120"</item>
+    <item msgid="537693705785480198">"311480"</item>
+  </string-array>
+</resources>
diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml
new file mode 100644
index 0000000..5a39f18
--- /dev/null
+++ b/res/values-as/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2008 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_label" product="tablet" msgid="9194799012395299737">"ম\'বাইল নেটৱৰ্ক কনফিগাৰেশ্বন"</string>
+    <string name="app_label" product="default" msgid="8338087656149558019">"ফ\'ন আৰু বাৰ্তাৰ সঞ্চয়াগাৰ"</string>
+</resources>
diff --git a/res/values-or/config.xml b/res/values-or/config.xml
new file mode 100644
index 0000000..99877a6
--- /dev/null
+++ b/res/values-or/config.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="persist_apns_for_plmn">
+    <item msgid="6413072509259000954">"20404"</item>
+    <item msgid="5639159280778239123">"310004"</item>
+    <item msgid="3860605521380788028">"310120"</item>
+    <item msgid="537693705785480198">"311480"</item>
+  </string-array>
+</resources>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
new file mode 100644
index 0000000..b004c4f
--- /dev/null
+++ b/res/values-or/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2008 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_label" product="tablet" msgid="9194799012395299737">"ମୋବାଇଲ୍ ନେଟ୍‌ୱର୍କ କନଫିଗରେଶନ୍"</string>
+    <string name="app_label" product="default" msgid="8338087656149558019">"ଫୋନ୍ ଓ ମେସେଜିଙ୍ଗ ଷ୍ଟୋରେଜ୍"</string>
+</resources>
diff --git a/src/com/android/providers/telephony/CarrierDatabaseHelper.java b/src/com/android/providers/telephony/CarrierDatabaseHelper.java
index b654a77..0b97da1 100644
--- a/src/com/android/providers/telephony/CarrierDatabaseHelper.java
+++ b/src/com/android/providers/telephony/CarrierDatabaseHelper.java
@@ -40,6 +40,7 @@
      */
     public CarrierDatabaseHelper(Context context) {
         super(context, DATABASE_NAME, null, DATABASE_VERSION);
+        setWriteAheadLoggingEnabled(false);
     }
 
     public static final String KEY_TYPE = "key_type";
diff --git a/src/com/android/providers/telephony/CarrierIdProvider.java b/src/com/android/providers/telephony/CarrierIdProvider.java
index 1c2e5e5..5e090dd 100644
--- a/src/com/android/providers/telephony/CarrierIdProvider.java
+++ b/src/com/android/providers/telephony/CarrierIdProvider.java
@@ -74,7 +74,7 @@
     private static final String TAG = CarrierIdProvider.class.getSimpleName();
 
     private static final String DATABASE_NAME = "carrierIdentification.db";
-    private static final int DATABASE_VERSION = 3;
+    private static final int DATABASE_VERSION = 4;
 
     private static final String ASSETS_PB_FILE = "carrier_list.pb";
     private static final String VERSION_KEY = "version";
@@ -119,10 +119,15 @@
     * index 7: {@link CarrierId.All#ICCID_PREFIX}
     */
     private static final int ICCID_PREFIX_INDEX          = 7;
+
+    /**
+     * index 8: {@link CarrierId.All#PRIVILEGE_ACCESS_RULE}
+     */
+    private static final int PRIVILEGE_ACCESS_RULE       = 8;
     /**
      * ending index of carrier attribute list.
      */
-    private static final int CARRIER_ATTR_END_IDX        = ICCID_PREFIX_INDEX;
+    private static final int CARRIER_ATTR_END_IDX        = PRIVILEGE_ACCESS_RULE;
     /**
      * The authority string for the CarrierIdProvider
      */
@@ -139,15 +144,17 @@
             CarrierId.All.IMSI_PREFIX_XPATTERN,
             CarrierId.All.SPN,
             CarrierId.All.APN,
-            CarrierId.All.ICCID_PREFIX));
+            CarrierId.All.ICCID_PREFIX,
+            CarrierId.All.PRIVILEGE_ACCESS_RULE));
 
     private CarrierIdDatabaseHelper mDbHelper;
 
     /**
      * Stores carrier id information for the current active subscriptions.
-     * Key is the active subId and entryValue is a pair of carrier id(int) and Carrier Name(String).
+     * Key is the active subId and entryValue is carrier id(int), mno carrier id (int) and
+     * carrier name(String).
      */
-    private final Map<Integer, Pair<Integer, String>> mCurrentSubscriptionMap =
+    private final Map<Integer, ContentValues> mCurrentSubscriptionMap =
             new ConcurrentHashMap<>();
 
     @VisibleForTesting
@@ -162,6 +169,7 @@
                 + CarrierId.All.SPN + " TEXT,"
                 + CarrierId.All.APN + " TEXT,"
                 + CarrierId.All.ICCID_PREFIX + " TEXT,"
+                + CarrierId.All.PRIVILEGE_ACCESS_RULE + " TEXT,"
                 + CarrierId.CARRIER_NAME + " TEXT,"
                 + CarrierId.CARRIER_ID + " INTEGER DEFAULT -1,"
                 + "UNIQUE (" + TextUtils.join(", ", CARRIERS_ID_UNIQUE_FIELDS) + "));";
@@ -317,6 +325,7 @@
          */
         public CarrierIdDatabaseHelper(Context context) {
             super(context, DATABASE_NAME, null, DATABASE_VERSION);
+            setWriteAheadLoggingEnabled(false);
         }
 
         @Override
@@ -472,6 +481,14 @@
                     found = true;
                 }
                 break;
+            case PRIVILEGE_ACCESS_RULE:
+                for (String str : attr.privilegeAccessRule) {
+                    cv.put(CarrierId.All.PRIVILEGE_ACCESS_RULE, str);
+                    convertCarrierAttrToContentValues(cv, cvs, attr, index + 1);
+                    cv.remove(CarrierId.All.PRIVILEGE_ACCESS_RULE);
+                    found = true;
+                }
+                break;
             default:
                 Log.e(TAG, "unsupported index: " + index);
                 break;
@@ -584,9 +601,7 @@
             }
             return count;
         } else {
-            mCurrentSubscriptionMap.put(subId,
-                    new Pair(cv.getAsInteger(CarrierId.CARRIER_ID),
-                    cv.getAsString(CarrierId.CARRIER_NAME)));
+            mCurrentSubscriptionMap.put(subId, new ContentValues(cv));
             getContext().getContentResolver().notifyChange(CarrierId.CONTENT_URI, null);
             return 1;
         }
@@ -618,9 +633,11 @@
         for (int i = 0; i < c.getColumnCount(); i++) {
             final String columnName = c.getColumnName(i);
             if (CarrierId.CARRIER_ID.equals(columnName)) {
-                row.add(mCurrentSubscriptionMap.get(subId).first);
+                row.add(mCurrentSubscriptionMap.get(subId).get(CarrierId.CARRIER_ID));
             } else if (CarrierId.CARRIER_NAME.equals(columnName)) {
-                row.add(mCurrentSubscriptionMap.get(subId).second);
+                row.add(mCurrentSubscriptionMap.get(subId).get(CarrierId.CARRIER_NAME));
+            } else if (CarrierId.MNO_CARRIER_ID.equals(columnName)) {
+                row.add(mCurrentSubscriptionMap.get(subId).get(CarrierId.MNO_CARRIER_ID));
             } else {
                 throw new IllegalArgumentException("Invalid column " + projectionIn[i]);
             }
diff --git a/src/com/android/providers/telephony/HbpcdLookupDatabaseHelper.java b/src/com/android/providers/telephony/HbpcdLookupDatabaseHelper.java
index 2debc57..0149687 100644
--- a/src/com/android/providers/telephony/HbpcdLookupDatabaseHelper.java
+++ b/src/com/android/providers/telephony/HbpcdLookupDatabaseHelper.java
@@ -102,6 +102,7 @@
         mContext = context;
         // Memory optimization - close idle connections after 30s of inactivity
         setIdleConnectionTimeout(IDLE_CONNECTION_TIMEOUT_MS);
+        setWriteAheadLoggingEnabled(false);
     }
 
     @Override
diff --git a/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java b/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
index b0265fa..f6855dc 100644
--- a/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
+++ b/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
@@ -24,6 +24,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
 import android.database.Cursor;
 import android.database.DatabaseErrorHandler;
 import android.database.DefaultDatabaseErrorHandler;
@@ -291,6 +292,7 @@
         mContext = context;
         // Memory optimization - close idle connections after 30s of inactivity
         setIdleConnectionTimeout(IDLE_CONNECTION_TIMEOUT_MS);
+        setWriteAheadLoggingEnabled(false);
         try {
             PhoneFactory.addLocalLog(TAG, 100);
         } catch (IllegalArgumentException e) {
@@ -1035,6 +1037,29 @@
                    Sms.TYPE + "=" + Sms.MESSAGE_TYPE_INBOX +
                    " OR " +
                    Sms.TYPE + "=" + Sms.MESSAGE_TYPE_SENT + ";");
+
+        if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
+            // Create a table to keep track of changes to SMS table - specifically on update to read
+            // and deletion of msgs
+            db.execSQL("CREATE TABLE sms_changes (" +
+                       "_id INTEGER PRIMARY KEY," +
+                       "orig_rowid INTEGER," +
+                       "sub_id INTEGER," +
+                       "type INTEGER," +
+                       "new_read_status INTEGER" +
+                       ");");
+            db.execSQL("CREATE TRIGGER sms_update_on_read_change_row " +
+                        "AFTER UPDATE OF read ON sms WHEN NEW.read != OLD.read " +
+                        "BEGIN " +
+                        "  INSERT INTO sms_changes VALUES(null, NEW._id, NEW.sub_id, " +
+                        "0, NEW.read); " +
+                        "END;");
+            db.execSQL("CREATE TRIGGER sms_delete_change_row " +
+                       "AFTER DELETE ON sms " +
+                       "BEGIN " +
+                       "  INSERT INTO sms_changes values(null, OLD._id, OLD.sub_id, 1, null); " +
+                       "END;");
+        }
     }
 
     private void createCommonTables(SQLiteDatabase db) {
diff --git a/src/com/android/providers/telephony/SmsChangesProvider.java b/src/com/android/providers/telephony/SmsChangesProvider.java
new file mode 100644
index 0000000..3f14e2b
--- /dev/null
+++ b/src/com/android/providers/telephony/SmsChangesProvider.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.providers.telephony;
+
+import android.app.AppOpsManager;
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.UriMatcher;
+import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.database.sqlite.SQLiteQueryBuilder;
+import android.net.Uri;
+import android.util.Log;
+
+/**
+ * This is the ContentProvider for the table sms_changes.
+ * This provider is applicable only for Android Auto builds as
+ * this table exists only in Android Auto environment.
+ *
+ * This provider does not notify of changes.
+ * Interested observers should instead listen to notification on sms table, instead.
+ */
+public class SmsChangesProvider extends ContentProvider {
+    private final static String TAG = "SmsChangesProvider";
+
+    private static final String TABLE_SMS_CHANGES = "sms_changes";
+
+    // Db open helper for tables stored in CE(Credential Encrypted) storage.
+    private SQLiteOpenHelper mCeOpenHelper;
+
+    @Override
+    public String getType(Uri url) {
+        return null;
+    }
+
+    @Override
+    public boolean onCreate() {
+        setAppOps(AppOpsManager.OP_READ_SMS, AppOpsManager.OP_WRITE_SMS);
+        mCeOpenHelper = MmsSmsDatabaseHelper.getInstanceForCe(getContext());
+        return true;
+    }
+
+
+    @Override
+    public Cursor query(Uri url, String[] projectionIn, String selection,
+            String[] selectionArgs, String sort) {
+        // return if FEATURE_AUTOMOTIVE is not set
+        if (!isAutoFeatureSet()) {
+            return null;
+        }
+
+        // Only support one type of query
+        //  Caller sends content://mms-sms and other params
+        if (!isUrlSupported(url)) {
+            return null;
+        }
+
+        SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
+        qb.setTables(TABLE_SMS_CHANGES);
+        SQLiteDatabase db = mCeOpenHelper.getReadableDatabase();
+        return qb.query(db, projectionIn, selection, selectionArgs,
+                null /* groupBy */, null /* having */,
+                null /* sortOrder */);
+    }
+
+    @Override
+    public Uri insert(Uri url, ContentValues initialValues) {
+        return null;
+    }
+
+    @Override
+    public int delete(Uri url, String where, String[] whereArgs) {
+        // return if FEATURE_AUTOMOTIVE is not set
+        if (!isAutoFeatureSet()) {
+            return 0;
+        }
+
+        // only support deletion of all data from the table
+        if (!isUrlSupported(url)) return 0;
+
+        return mCeOpenHelper.getWritableDatabase().delete(TABLE_SMS_CHANGES,
+                null /* whereClause */, null /* whereArgs */);
+    }
+
+    private boolean isUrlSupported(Uri url) {
+        if (sURLMatcher.match(url) != SMSCHANGES_URL) {
+            Log.e(TAG, "Invalid or Unsupported request: " + url);
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public int update(Uri url, ContentValues values, String where, String[] whereArgs) {
+        return 0;
+    }
+
+    private boolean isAutoFeatureSet() {
+        return getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
+    }
+
+    private static final int SMSCHANGES_URL = 0;
+
+    private static final UriMatcher sURLMatcher =
+            new UriMatcher(UriMatcher.NO_MATCH);
+
+    static {
+        sURLMatcher.addURI("sms-changes", null, SMSCHANGES_URL);
+    }
+}
diff --git a/src/com/android/providers/telephony/SmsProvider.java b/src/com/android/providers/telephony/SmsProvider.java
index 2b40d7e..2bf7378 100644
--- a/src/com/android/providers/telephony/SmsProvider.java
+++ b/src/com/android/providers/telephony/SmsProvider.java
@@ -16,6 +16,9 @@
 
 package com.android.providers.telephony;
 
+import static android.app.AppOpsManager.MODE_ALLOWED;
+import static android.app.AppOpsManager.MODE_IGNORED;
+
 import android.annotation.NonNull;
 import android.app.AppOpsManager;
 import android.content.ContentProvider;
@@ -33,6 +36,7 @@
 import android.os.Binder;
 import android.os.UserHandle;
 import android.provider.Contacts;
+import android.provider.Settings;
 import android.provider.Telephony;
 import android.provider.Telephony.MmsSms;
 import android.provider.Telephony.Sms;
@@ -847,6 +851,19 @@
         }
     }
 
+    /** @hide */
+    @Override
+    protected int interpretDefaultAppOpMode(int op) {
+        if (op == AppOpsManager.OP_WRITE_SMS) {
+            return MODE_IGNORED;
+        } else {
+            boolean accessRestrictionEnabled = Settings.Global.getInt(
+                    getContext().getContentResolver(),
+                    Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED, 0) == 1;
+            return accessRestrictionEnabled ? MODE_IGNORED : MODE_ALLOWED;
+        }
+    }
+
     // Db open helper for tables stored in CE(Credential Encrypted) storage.
     @VisibleForTesting
     public SQLiteOpenHelper mCeOpenHelper;
diff --git a/src/com/android/providers/telephony/TelephonyProvider.java b/src/com/android/providers/telephony/TelephonyProvider.java
index fffd78c..b2a3db8 100644
--- a/src/com/android/providers/telephony/TelephonyProvider.java
+++ b/src/com/android/providers/telephony/TelephonyProvider.java
@@ -456,6 +456,7 @@
             mContext = context;
             // Memory optimization - close idle connections after 30s of inactivity
             setIdleConnectionTimeout(IDLE_CONNECTION_TIMEOUT_MS);
+            setWriteAheadLoggingEnabled(false);
         }
 
         @VisibleForTesting
diff --git a/tests/src/com/android/providers/telephony/CarrierIdProviderTest.java b/tests/src/com/android/providers/telephony/CarrierIdProviderTest.java
index 44d9ec9..e5dd6e6 100644
--- a/tests/src/com/android/providers/telephony/CarrierIdProviderTest.java
+++ b/tests/src/com/android/providers/telephony/CarrierIdProviderTest.java
@@ -68,6 +68,8 @@
     private static final String dummy_apn = "APN_DUMMY";
     private static final String dummy_iccid_prefix = "ICCID_PREFIX_DUMMY";
     private static final String dummy_name = "NAME_DUMMY";
+    private static final String dummy_access_rule =
+            "B9CFCE1C47A6AC713442718F15EF55B00B3A6D1A6D48CB46249FA8EB51465350";
     private static final int dummy_cid = 0;
 
     private MockContextWithProvider mContext;
@@ -433,6 +435,7 @@
         contentValues.put(CarrierId.All.ICCID_PREFIX, dummy_iccid_prefix);
         contentValues.put(CarrierId.CARRIER_NAME, dummy_name);
         contentValues.put(CarrierId.CARRIER_ID, dummy_cid);
+        contentValues.put(CarrierId.All.PRIVILEGE_ACCESS_RULE, dummy_access_rule);
         return contentValues;
     }
 }