Merge "Snap for 9979206 from 5519d4c1f3ffbc5a1e1cf2f79246df88038f45ef to sdk-release" into sdk-release
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 6633d14..368bfbd 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -41,6 +41,8 @@
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
<!-- Allows accessing the messages on ICC -->
<uses-permission android:name="android.permission.ACCESS_MESSAGES_ON_ICC" />
+ <!-- Needed to query user associated with a subscription. -->
+ <uses-permission android:name="android.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION"/>
<application android:process="com.android.phone"
android:allowClearUserData="false"
diff --git a/assets/latest_carrier_id/carrier_list.pb b/assets/latest_carrier_id/carrier_list.pb
index a32f252..07f8dad 100644
--- a/assets/latest_carrier_id/carrier_list.pb
+++ b/assets/latest_carrier_id/carrier_list.pb
Binary files differ
diff --git a/assets/latest_carrier_id/carrier_list.textpb b/assets/latest_carrier_id/carrier_list.textpb
index eb25105..50f1afc 100644
--- a/assets/latest_carrier_id/carrier_list.textpb
+++ b/assets/latest_carrier_id/carrier_list.textpb
@@ -5792,6 +5792,7 @@
carrier_name: "Copper Valley Wireless"
carrier_attribute {
mccmnc_tuple: "310930"
+ mccmnc_tuple: "312380"
}
}
carrier_id {
@@ -6413,6 +6414,12 @@
canonical_id: 1910
carrier_name: "COX"
carrier_attribute {
+ mccmnc_tuple: "311480"
+ spn: "Cox Mobile"
+ gid1: "BA01570000000000"
+ gid2: "B100000000000000"
+ }
+ carrier_attribute {
mccmnc_tuple: "311600"
}
}
@@ -6870,10 +6877,6 @@
mccmnc_tuple: "302370"
gid1: "DD"
}
- carrier_attribute {
- mccmnc_tuple: "302370"
- mccmnc_tuple: "30237"
- }
}
carrier_id {
canonical_id: 1963
@@ -7901,13 +7904,9 @@
carrier_attribute {
mccmnc_tuple: "26201"
mccmnc_tuple: "26206"
- gid1: "44"
- }
- carrier_attribute {
- mccmnc_tuple: "26201"
- mccmnc_tuple: "26206"
spn: "congstar"
spn: "congstar.de"
+ gid1: "44"
}
}
carrier_id {
@@ -9679,6 +9678,9 @@
mccmnc_tuple: "310960"
spn: "strata"
}
+ carrier_attribute {
+ mccmnc_tuple: "312290"
+ }
}
carrier_id {
canonical_id: 2321
@@ -10944,6 +10946,14 @@
}
}
carrier_id {
+ canonical_id: 2503
+ carrier_name: "Boost"
+ carrier_attribute {
+ mccmnc_tuple: "50501"
+ spn: "BOOST"
+ }
+}
+carrier_id {
canonical_id: 2504
carrier_name: "Liberty Mobile"
carrier_attribute {
@@ -11205,6 +11215,9 @@
canonical_id: 2536
carrier_name: "1&1"
carrier_attribute {
+ mccmnc_tuple: "26223"
+ }
+ carrier_attribute {
mccmnc_tuple: "26207"
gid1: "118004"
gid1: "118006"
@@ -11388,6 +11401,16 @@
}
}
carrier_id {
+ canonical_id: 2557
+ carrier_name: "fraenk"
+ carrier_attribute {
+ mccmnc_tuple: "26201"
+ mccmnc_tuple: "26206"
+ spn: "fraenk"
+ gid1: "44"
+ }
+}
+carrier_id {
canonical_id: 2558
carrier_name: "Wintel"
carrier_attribute {
@@ -11395,14 +11418,78 @@
}
}
carrier_id {
+ canonical_id: 2559
+ carrier_name: "MONACO TELECOM"
+ carrier_attribute {
+ mccmnc_tuple: "212010"
+ }
+}
+carrier_id {
+ canonical_id: 2560
+ carrier_name: "U+264A"
+ carrier_attribute {
+ mccmnc_tuple: "23210"
+ gid1: "040D"
+ }
+ carrier_attribute {
+ mccmnc_tuple: "23210"
+ gid1: "040E"
+ }
+ carrier_attribute {
+ mccmnc_tuple: "302760"
+ gid1: "F1"
+ }
+ carrier_attribute {
+ mccmnc_tuple: "310240"
+ gid1: "4280"
+ }
+}
+carrier_id {
+ canonical_id: 2561
+ carrier_name: "Lebara"
+ carrier_attribute {
+ mccmnc_tuple: "20838"
+ spn: "Lebara"
+ }
+}
+carrier_id {
+ canonical_id: 2562
+ carrier_name: "Lebara"
+ carrier_attribute {
+ mccmnc_tuple: "26214"
+ spn: "Lebara"
+ }
+}
+carrier_id {
+ canonical_id: 2563
+ carrier_name: "Lebara"
+ carrier_attribute {
+ mccmnc_tuple: "20417"
+ spn: "Lebara"
+ }
+}
+carrier_id {
+ canonical_id: 2564
+ carrier_name: "Lebara"
+ carrier_attribute {
+ mccmnc_tuple: "23487"
+ spn: "Lebara"
+ }
+}
+carrier_id {
canonical_id: 10000
carrier_name: "Tracfone-ATT"
carrier_attribute {
mccmnc_tuple: "310280"
mccmnc_tuple: "310410"
+ mccmnc_tuple: "311180"
gid1: "DDFF"
gid1: "DEFF"
}
+ carrier_attribute {
+ mccmnc_tuple: "310950"
+ gid1: "DDFF"
+ }
parent_canonical_id: 2022
}
carrier_id {
@@ -11727,4 +11814,40 @@
}
parent_canonical_id: 2531
}
-version: 67108886
+carrier_id {
+ canonical_id: 10032
+ carrier_name: "U+264A-3AT Operational"
+ carrier_attribute {
+ mccmnc_tuple: "23210"
+ gid1: "040D"
+ }
+ parent_canonical_id: 2560
+}
+carrier_id {
+ canonical_id: 10033
+ carrier_name: "U+264A-3AT Provisioning"
+ carrier_attribute {
+ mccmnc_tuple: "23210"
+ gid1: "040E"
+ }
+ parent_canonical_id: 2560
+}
+carrier_id {
+ canonical_id: 10034
+ carrier_name: "U+264A-Telus"
+ carrier_attribute {
+ mccmnc_tuple: "302760"
+ gid1: "F1"
+ }
+ parent_canonical_id: 2560
+}
+carrier_id {
+ canonical_id: 10035
+ carrier_name: "U+264A-TMO"
+ carrier_attribute {
+ mccmnc_tuple: "310240"
+ gid1: "4280"
+ }
+ parent_canonical_id: 2560
+}
+version: 67108889
diff --git a/assets/sdk28_carrier_id/carrier_list.pb b/assets/sdk28_carrier_id/carrier_list.pb
index fa1819c..bd8ff56 100644
--- a/assets/sdk28_carrier_id/carrier_list.pb
+++ b/assets/sdk28_carrier_id/carrier_list.pb
Binary files differ
diff --git a/assets/sdk28_carrier_id/carrier_list.textpb b/assets/sdk28_carrier_id/carrier_list.textpb
index 5a145c2..0aa6304 100644
--- a/assets/sdk28_carrier_id/carrier_list.textpb
+++ b/assets/sdk28_carrier_id/carrier_list.textpb
@@ -6306,6 +6306,9 @@
carrier_attribute {
mccmnc_tuple: "310930"
}
+ carrier_attribute {
+ mccmnc_tuple: "312380"
+ }
}
carrier_id {
canonical_id: 1831
@@ -6954,6 +6957,12 @@
carrier_attribute {
mccmnc_tuple: "311600"
}
+ carrier_attribute {
+ mccmnc_tuple: "311480"
+ spn: "Cox Mobile"
+ gid1: "BA01570000000000"
+ gid2: "B100000000000000"
+ }
}
carrier_id {
canonical_id: 1911
@@ -8688,6 +8697,16 @@
spn: "congstar"
spn: "congstar.de"
}
+ carrier_attribute {
+ mccmnc_tuple: "26206"
+ spn: "congstar"
+ gid1: "44"
+ }
+ carrier_attribute {
+ mccmnc_tuple: "26206"
+ spn: "congstar.de"
+ gid1: "44"
+ }
}
carrier_id {
canonical_id: 2093
@@ -10519,6 +10538,9 @@
mccmnc_tuple: "310960"
spn: "strata"
}
+ carrier_attribute {
+ mccmnc_tuple: "312290"
+ }
}
carrier_id {
canonical_id: 2321
@@ -12000,6 +12022,9 @@
imsi_prefix_xpattern: "26207414x"
gid1: "250109"
}
+ carrier_attribute {
+ mccmnc_tuple: "26223"
+ }
}
carrier_id {
canonical_id: 2538
@@ -12205,6 +12230,15 @@
}
}
carrier_id {
+ canonical_id: 2557
+ carrier_name: "fraenk"
+ carrier_attribute {
+ mccmnc_tuple: "26206"
+ spn: "fraenk"
+ gid1: "44"
+ }
+}
+carrier_id {
canonical_id: 2558
carrier_name: "Wintel"
carrier_attribute {
@@ -12212,6 +12246,65 @@
}
}
carrier_id {
+ canonical_id: 2559
+ carrier_name: "MONACO TELECOM"
+ carrier_attribute {
+ mccmnc_tuple: "212010"
+ }
+}
+carrier_id {
+ canonical_id: 2560
+ carrier_name: "U+264A"
+ carrier_attribute {
+ mccmnc_tuple: "23210"
+ gid1: "040D"
+ }
+ carrier_attribute {
+ mccmnc_tuple: "23210"
+ gid1: "040E"
+ }
+ carrier_attribute {
+ mccmnc_tuple: "302760"
+ gid1: "F1"
+ }
+ carrier_attribute {
+ mccmnc_tuple: "310240"
+ gid1: "4280"
+ }
+}
+carrier_id {
+ canonical_id: 2561
+ carrier_name: "Lebara"
+ carrier_attribute {
+ mccmnc_tuple: "20838"
+ spn: "Lebara"
+ }
+}
+carrier_id {
+ canonical_id: 2562
+ carrier_name: "Lebara"
+ carrier_attribute {
+ mccmnc_tuple: "26214"
+ spn: "Lebara"
+ }
+}
+carrier_id {
+ canonical_id: 2563
+ carrier_name: "Lebara"
+ carrier_attribute {
+ mccmnc_tuple: "20417"
+ spn: "Lebara"
+ }
+}
+carrier_id {
+ canonical_id: 2564
+ carrier_name: "Lebara"
+ carrier_attribute {
+ mccmnc_tuple: "23487"
+ spn: "Lebara"
+ }
+}
+carrier_id {
canonical_id: 10000
carrier_name: "Tracfone-ATT"
carrier_attribute {
@@ -12453,4 +12546,4 @@
}
parent_canonical_id: 2023
}
-version: 30
+version: 33
diff --git a/assets/sdk29_carrier_id/carrier_list.pb b/assets/sdk29_carrier_id/carrier_list.pb
index b0f3743..0ad55d2 100644
--- a/assets/sdk29_carrier_id/carrier_list.pb
+++ b/assets/sdk29_carrier_id/carrier_list.pb
Binary files differ
diff --git a/assets/sdk29_carrier_id/carrier_list.textpb b/assets/sdk29_carrier_id/carrier_list.textpb
index cecfcee..e9d37aa 100644
--- a/assets/sdk29_carrier_id/carrier_list.textpb
+++ b/assets/sdk29_carrier_id/carrier_list.textpb
@@ -6121,6 +6121,9 @@
carrier_attribute {
mccmnc_tuple: "310930"
}
+ carrier_attribute {
+ mccmnc_tuple: "312380"
+ }
}
carrier_id {
canonical_id: 1831
@@ -6772,6 +6775,12 @@
carrier_attribute {
mccmnc_tuple: "311600"
}
+ carrier_attribute {
+ mccmnc_tuple: "311480"
+ spn: "Cox Mobile"
+ gid1: "BA01570000000000"
+ gid2: "B100000000000000"
+ }
}
carrier_id {
canonical_id: 1911
@@ -8428,6 +8437,16 @@
spn: "congstar"
spn: "congstar.de"
}
+ carrier_attribute {
+ mccmnc_tuple: "26206"
+ spn: "congstar"
+ gid1: "44"
+ }
+ carrier_attribute {
+ mccmnc_tuple: "26206"
+ spn: "congstar.de"
+ gid1: "44"
+ }
}
carrier_id {
canonical_id: 2093
@@ -10253,6 +10272,9 @@
mccmnc_tuple: "310960"
spn: "strata"
}
+ carrier_attribute {
+ mccmnc_tuple: "312290"
+ }
}
carrier_id {
canonical_id: 2321
@@ -11816,6 +11838,9 @@
imsi_prefix_xpattern: "26207414x"
gid1: "250109"
}
+ carrier_attribute {
+ mccmnc_tuple: "26223"
+ }
}
carrier_id {
canonical_id: 2538
@@ -12021,6 +12046,15 @@
}
}
carrier_id {
+ canonical_id: 2557
+ carrier_name: "fraenk"
+ carrier_attribute {
+ mccmnc_tuple: "26206"
+ spn: "fraenk"
+ gid1: "44"
+ }
+}
+carrier_id {
canonical_id: 2558
carrier_name: "Wintel"
carrier_attribute {
@@ -12028,6 +12062,65 @@
}
}
carrier_id {
+ canonical_id: 2559
+ carrier_name: "MONACO TELECOM"
+ carrier_attribute {
+ mccmnc_tuple: "212010"
+ }
+}
+carrier_id {
+ canonical_id: 2560
+ carrier_name: "U+264A"
+ carrier_attribute {
+ mccmnc_tuple: "23210"
+ gid1: "040D"
+ }
+ carrier_attribute {
+ mccmnc_tuple: "23210"
+ gid1: "040E"
+ }
+ carrier_attribute {
+ mccmnc_tuple: "302760"
+ gid1: "F1"
+ }
+ carrier_attribute {
+ mccmnc_tuple: "310240"
+ gid1: "4280"
+ }
+}
+carrier_id {
+ canonical_id: 2561
+ carrier_name: "Lebara"
+ carrier_attribute {
+ mccmnc_tuple: "20838"
+ spn: "Lebara"
+ }
+}
+carrier_id {
+ canonical_id: 2562
+ carrier_name: "Lebara"
+ carrier_attribute {
+ mccmnc_tuple: "26214"
+ spn: "Lebara"
+ }
+}
+carrier_id {
+ canonical_id: 2563
+ carrier_name: "Lebara"
+ carrier_attribute {
+ mccmnc_tuple: "20417"
+ spn: "Lebara"
+ }
+}
+carrier_id {
+ canonical_id: 2564
+ carrier_name: "Lebara"
+ carrier_attribute {
+ mccmnc_tuple: "23487"
+ spn: "Lebara"
+ }
+}
+carrier_id {
canonical_id: 10000
carrier_name: "Tracfone-ATT"
carrier_attribute {
@@ -12268,4 +12361,4 @@
}
parent_canonical_id: 2023
}
-version: 16777254
+version: 16777257
diff --git a/assets/sdk30_carrier_id/carrier_list.pb b/assets/sdk30_carrier_id/carrier_list.pb
index 6534a58..62d3275 100644
--- a/assets/sdk30_carrier_id/carrier_list.pb
+++ b/assets/sdk30_carrier_id/carrier_list.pb
Binary files differ
diff --git a/assets/sdk30_carrier_id/carrier_list.textpb b/assets/sdk30_carrier_id/carrier_list.textpb
index 15a960d..0bd892d 100644
--- a/assets/sdk30_carrier_id/carrier_list.textpb
+++ b/assets/sdk30_carrier_id/carrier_list.textpb
@@ -6118,6 +6118,9 @@
carrier_attribute {
mccmnc_tuple: "310930"
}
+ carrier_attribute {
+ mccmnc_tuple: "312380"
+ }
}
carrier_id {
canonical_id: 1831
@@ -6769,6 +6772,12 @@
carrier_attribute {
mccmnc_tuple: "311600"
}
+ carrier_attribute {
+ mccmnc_tuple: "311480"
+ spn: "Cox Mobile"
+ gid1: "BA01570000000000"
+ gid2: "B100000000000000"
+ }
}
carrier_id {
canonical_id: 1911
@@ -8395,6 +8404,16 @@
spn: "congstar"
spn: "congstar.de"
}
+ carrier_attribute {
+ mccmnc_tuple: "26206"
+ spn: "congstar"
+ gid1: "44"
+ }
+ carrier_attribute {
+ mccmnc_tuple: "26206"
+ spn: "congstar.de"
+ gid1: "44"
+ }
}
carrier_id {
canonical_id: 2093
@@ -10227,6 +10246,9 @@
mccmnc_tuple: "310960"
spn: "strata"
}
+ carrier_attribute {
+ mccmnc_tuple: "312290"
+ }
}
carrier_id {
canonical_id: 2321
@@ -11804,6 +11826,9 @@
imsi_prefix_xpattern: "26207414x"
gid1: "250109"
}
+ carrier_attribute {
+ mccmnc_tuple: "26223"
+ }
}
carrier_id {
canonical_id: 2538
@@ -12009,6 +12034,15 @@
}
}
carrier_id {
+ canonical_id: 2557
+ carrier_name: "fraenk"
+ carrier_attribute {
+ mccmnc_tuple: "26206"
+ spn: "fraenk"
+ gid1: "44"
+ }
+}
+carrier_id {
canonical_id: 2558
carrier_name: "Wintel"
carrier_attribute {
@@ -12016,6 +12050,65 @@
}
}
carrier_id {
+ canonical_id: 2559
+ carrier_name: "MONACO TELECOM"
+ carrier_attribute {
+ mccmnc_tuple: "212010"
+ }
+}
+carrier_id {
+ canonical_id: 2560
+ carrier_name: "U+264A"
+ carrier_attribute {
+ mccmnc_tuple: "23210"
+ gid1: "040D"
+ }
+ carrier_attribute {
+ mccmnc_tuple: "23210"
+ gid1: "040E"
+ }
+ carrier_attribute {
+ mccmnc_tuple: "302760"
+ gid1: "F1"
+ }
+ carrier_attribute {
+ mccmnc_tuple: "310240"
+ gid1: "4280"
+ }
+}
+carrier_id {
+ canonical_id: 2561
+ carrier_name: "Lebara"
+ carrier_attribute {
+ mccmnc_tuple: "20838"
+ spn: "Lebara"
+ }
+}
+carrier_id {
+ canonical_id: 2562
+ carrier_name: "Lebara"
+ carrier_attribute {
+ mccmnc_tuple: "26214"
+ spn: "Lebara"
+ }
+}
+carrier_id {
+ canonical_id: 2563
+ carrier_name: "Lebara"
+ carrier_attribute {
+ mccmnc_tuple: "20417"
+ spn: "Lebara"
+ }
+}
+carrier_id {
+ canonical_id: 2564
+ carrier_name: "Lebara"
+ carrier_attribute {
+ mccmnc_tuple: "23487"
+ spn: "Lebara"
+ }
+}
+carrier_id {
canonical_id: 10000
carrier_name: "Tracfone-ATT"
carrier_attribute {
@@ -12276,4 +12369,4 @@
}
parent_canonical_id: 2023
}
-version: 33554488
+version: 33554491
diff --git a/assets/sdk31_carrier_id/carrier_list.pb b/assets/sdk31_carrier_id/carrier_list.pb
index 75c4751..8f94b2e 100644
--- a/assets/sdk31_carrier_id/carrier_list.pb
+++ b/assets/sdk31_carrier_id/carrier_list.pb
Binary files differ
diff --git a/assets/sdk31_carrier_id/carrier_list.textpb b/assets/sdk31_carrier_id/carrier_list.textpb
index f3e3180..032d22b 100644
--- a/assets/sdk31_carrier_id/carrier_list.textpb
+++ b/assets/sdk31_carrier_id/carrier_list.textpb
@@ -5856,6 +5856,9 @@
carrier_attribute {
mccmnc_tuple: "310930"
}
+ carrier_attribute {
+ mccmnc_tuple: "312380"
+ }
}
carrier_id {
canonical_id: 1831
@@ -6501,6 +6504,12 @@
carrier_attribute {
mccmnc_tuple: "311600"
}
+ carrier_attribute {
+ mccmnc_tuple: "311480"
+ spn: "Cox Mobile"
+ gid1: "BA01570000000000"
+ gid2: "B100000000000000"
+ }
}
carrier_id {
canonical_id: 1911
@@ -8124,6 +8133,16 @@
spn: "congstar"
spn: "congstar.de"
}
+ carrier_attribute {
+ mccmnc_tuple: "26206"
+ spn: "congstar"
+ gid1: "44"
+ }
+ carrier_attribute {
+ mccmnc_tuple: "26206"
+ spn: "congstar.de"
+ gid1: "44"
+ }
}
carrier_id {
canonical_id: 2093
@@ -9921,6 +9940,9 @@
mccmnc_tuple: "310960"
spn: "strata"
}
+ carrier_attribute {
+ mccmnc_tuple: "312290"
+ }
}
carrier_id {
canonical_id: 2321
@@ -11482,6 +11504,9 @@
imsi_prefix_xpattern: "26207414x"
gid1: "250109"
}
+ carrier_attribute {
+ mccmnc_tuple: "26223"
+ }
}
carrier_id {
canonical_id: 2538
@@ -11694,6 +11719,15 @@
}
}
carrier_id {
+ canonical_id: 2557
+ carrier_name: "fraenk"
+ carrier_attribute {
+ mccmnc_tuple: "26206"
+ spn: "fraenk"
+ gid1: "44"
+ }
+}
+carrier_id {
canonical_id: 2558
carrier_name: "Wintel"
carrier_attribute {
@@ -11701,6 +11735,65 @@
}
}
carrier_id {
+ canonical_id: 2559
+ carrier_name: "MONACO TELECOM"
+ carrier_attribute {
+ mccmnc_tuple: "212010"
+ }
+}
+carrier_id {
+ canonical_id: 2560
+ carrier_name: "U+264A"
+ carrier_attribute {
+ mccmnc_tuple: "23210"
+ gid1: "040D"
+ }
+ carrier_attribute {
+ mccmnc_tuple: "23210"
+ gid1: "040E"
+ }
+ carrier_attribute {
+ mccmnc_tuple: "302760"
+ gid1: "F1"
+ }
+ carrier_attribute {
+ mccmnc_tuple: "310240"
+ gid1: "4280"
+ }
+}
+carrier_id {
+ canonical_id: 2561
+ carrier_name: "Lebara"
+ carrier_attribute {
+ mccmnc_tuple: "20838"
+ spn: "Lebara"
+ }
+}
+carrier_id {
+ canonical_id: 2562
+ carrier_name: "Lebara"
+ carrier_attribute {
+ mccmnc_tuple: "26214"
+ spn: "Lebara"
+ }
+}
+carrier_id {
+ canonical_id: 2563
+ carrier_name: "Lebara"
+ carrier_attribute {
+ mccmnc_tuple: "20417"
+ spn: "Lebara"
+ }
+}
+carrier_id {
+ canonical_id: 2564
+ carrier_name: "Lebara"
+ carrier_attribute {
+ mccmnc_tuple: "23487"
+ spn: "Lebara"
+ }
+}
+carrier_id {
canonical_id: 10000
carrier_name: "Tracfone-ATT"
carrier_attribute {
@@ -12001,4 +12094,4 @@
}
parent_canonical_id: 1894
}
-version: 50331680
+version: 50331683
diff --git a/src/com/android/providers/telephony/MmsProvider.java b/src/com/android/providers/telephony/MmsProvider.java
index bc41208..26af21c 100644
--- a/src/com/android/providers/telephony/MmsProvider.java
+++ b/src/com/android/providers/telephony/MmsProvider.java
@@ -25,6 +25,8 @@
import android.content.Intent;
import android.content.UriMatcher;
import android.database.Cursor;
+import android.database.DatabaseUtils;
+import android.database.MatrixCursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
@@ -44,11 +46,14 @@
import android.provider.Telephony.Threads;
import android.system.ErrnoException;
import android.system.Os;
+import android.telephony.SmsManager;
+import android.telephony.SubscriptionManager;
import android.text.TextUtils;
import android.util.EventLog;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.TelephonyPermissions;
import com.google.android.mms.pdu.PduHeaders;
import com.google.android.mms.util.DownloadDrmHelper;
@@ -109,12 +114,14 @@
@Override
public Cursor query(Uri uri, String[] projection,
String selection, String[] selectionArgs, String sortOrder) {
+ final int callerUid = Binder.getCallingUid();
+ final UserHandle callerUserHandle = Binder.getCallingUserHandle();
// First check if a restricted view of the "pdu" table should be used based on the
// caller's identity. Only system, phone or the default sms app can have full access
// of mms data. For other apps, we present a restricted view which only contains sent
// or received messages, without wap pushes.
final boolean accessRestricted = ProviderUtil.isAccessRestricted(
- getContext(), getCallingPackage(), Binder.getCallingUid());
+ getContext(), getCallingPackage(), callerUid);
// If access is restricted, we don't allow subqueries in the query.
if (accessRestricted) {
@@ -247,6 +254,23 @@
return null;
}
+ if (qb.getTables().equals(pduTable)) {
+ String selectionBySubIds;
+ final long token = Binder.clearCallingIdentity();
+ try {
+ // Filter MMS based on subId.
+ selectionBySubIds = ProviderUtil.getSelectionBySubIds(getContext(),
+ callerUserHandle);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ if (selectionBySubIds == null) {
+ // No subscriptions associated with user, return empty cursor.
+ return new MatrixCursor((projection == null) ? (new String[] {}) : projection);
+ }
+ selection = DatabaseUtils.concatenateWhere(selection, selectionBySubIds);
+ }
+
String finalSortOrder = null;
if (TextUtils.isEmpty(sortOrder)) {
if (qb.getTables().equals(pduTable)) {
@@ -328,6 +352,7 @@
@Override
public Uri insert(Uri uri, ContentValues values) {
final int callerUid = Binder.getCallingUid();
+ final UserHandle callerUserHandle = Binder.getCallingUserHandle();
final String callerPkg = getCallingPackage();
int msgBox = Mms.MESSAGE_BOX_ALL;
boolean notify = true;
@@ -337,7 +362,7 @@
values.remove(TelephonyBackupAgent.NOTIFY);
// check isAccessRestricted to prevent third parties from setting NOTIFY = false maliciously
if (forceNoNotify && !providerUtilWrapper.isAccessRestricted(
- getContext(), getCallingPackage(), Binder.getCallingUid())) {
+ getContext(), getCallingPackage(), callerUid)) {
notify = false;
}
@@ -398,6 +423,22 @@
long rowId;
if (table.equals(TABLE_PDU)) {
+ int subId;
+ if (values.containsKey(Telephony.Sms.SUBSCRIPTION_ID)) {
+ subId = values.getAsInteger(Telephony.Sms.SUBSCRIPTION_ID);
+ } else {
+ subId = SmsManager.getDefaultSmsSubscriptionId();
+ if (SubscriptionManager.isValidSubscriptionId(subId)) {
+ values.put(Telephony.Sms.SUBSCRIPTION_ID, subId);
+ }
+ }
+
+ if (!TelephonyPermissions
+ .checkSubscriptionAssociatedWithUser(getContext(), subId, callerUserHandle)) {
+ // TODO(b/258629881): Display error dialog.
+ return null;
+ }
+
boolean addDate = !values.containsKey(Mms.DATE);
boolean addMsgBox = !values.containsKey(Mms.MESSAGE_BOX);
@@ -655,6 +696,7 @@
@Override
public int delete(Uri uri, String selection,
String[] selectionArgs) {
+ final UserHandle callerUserHandle = Binder.getCallingUserHandle();
int match = sURLMatcher.match(uri);
if (LOCAL_LOGV) {
Log.v(TAG, "Delete uri=" + uri + ", match=" + match);
@@ -713,6 +755,21 @@
int deletedRows = 0;
if (TABLE_PDU.equals(table)) {
+ final long token = Binder.clearCallingIdentity();
+ String selectionBySubIds;
+ try {
+ // Filter SMS based on subId.
+ selectionBySubIds = ProviderUtil.getSelectionBySubIds(getContext(),
+ callerUserHandle);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ if (selectionBySubIds == null) {
+ // No subscriptions associated with user, return 0.
+ return 0;
+ }
+ finalSelection = DatabaseUtils.concatenateWhere(finalSelection, selectionBySubIds);
+
deletedRows = deleteMessages(getContext(), db, finalSelection,
selectionArgs, uri);
} else if (TABLE_PART.equals(table)) {
@@ -816,6 +873,7 @@
return 0;
}
final int callerUid = Binder.getCallingUid();
+ final UserHandle callerUserHandle = Binder.getCallingUserHandle();
final String callerPkg = getCallingPackage();
int match = sURLMatcher.match(uri);
if (LOCAL_LOGV) {
@@ -856,7 +914,7 @@
String partsDirPath = getContext().getDir(PARTS_DIR_NAME, 0).getCanonicalPath();
if (!new File(path).getCanonicalPath().startsWith(partsDirPath)) {
EventLog.writeEvent(0x534e4554, "240685104",
- Binder.getCallingUid(), (TAG + " update: path " + path +
+ callerUid, (TAG + " update: path " + path +
" does not start with " + partsDirPath));
return 0;
}
@@ -890,6 +948,21 @@
if (msgId != null) {
extraSelection = Mms._ID + "=" + msgId;
}
+
+ final long token = Binder.clearCallingIdentity();
+ String selectionBySubIds;
+ try {
+ // Filter MMS based on subId.
+ selectionBySubIds = ProviderUtil.getSelectionBySubIds(getContext(),
+ callerUserHandle);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ if (selectionBySubIds == null) {
+ // No subscriptions associated with user, return 0.
+ return 0;
+ }
+ extraSelection = DatabaseUtils.concatenateWhere(extraSelection, selectionBySubIds);
} else if (table.equals(TABLE_PART)) {
finalValues = new ContentValues(values);
diff --git a/src/com/android/providers/telephony/MmsSmsProvider.java b/src/com/android/providers/telephony/MmsSmsProvider.java
index 904e2ba..41b2fd7 100644
--- a/src/com/android/providers/telephony/MmsSmsProvider.java
+++ b/src/com/android/providers/telephony/MmsSmsProvider.java
@@ -23,6 +23,7 @@
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.DatabaseUtils;
+import android.database.MatrixCursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
@@ -40,9 +41,12 @@
import android.provider.Telephony.Sms.Conversations;
import android.provider.Telephony.Threads;
import android.provider.Telephony.ThreadsColumns;
+import android.telephony.SmsManager;
+import android.telephony.SubscriptionManager;
import android.text.TextUtils;
import android.util.Log;
+import com.android.internal.telephony.TelephonyPermissions;
import com.android.internal.telephony.TelephonyStatsLog;
import com.google.android.mms.pdu.PduHeaders;
@@ -329,12 +333,15 @@
@Override
public Cursor query(Uri uri, String[] projection,
String selection, String[] selectionArgs, String sortOrder) {
+ final int callerUid = Binder.getCallingUid();
+ final UserHandle callerUserHandle = Binder.getCallingUserHandle();
+
// First check if restricted views of the "sms" and "pdu" tables should be used based on the
// caller's identity. Only system, phone or the default sms app can have full access
// of sms/mms data. For other apps, we present a restricted view which only contains sent
// or received messages, without wap pushes.
final boolean accessRestricted = ProviderUtil.isAccessRestricted(
- getContext(), getCallingPackage(), Binder.getCallingUid());
+ getContext(), getCallingPackage(), callerUid);
final String pduTable = MmsProvider.getPduTable(accessRestricted);
final String smsTable = SmsProvider.getSmsTable(accessRestricted);
@@ -348,11 +355,28 @@
}
}
+ String selectionBySubIds;
+ final long token = Binder.clearCallingIdentity();
+ try {
+ // Filter MMS/SMS based on subId
+ selectionBySubIds = ProviderUtil.getSelectionBySubIds(getContext(), callerUserHandle);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+
SQLiteDatabase db = mOpenHelper.getReadableDatabase();
Cursor cursor = null;
+ Cursor emptyCursor = new MatrixCursor((projection == null) ?
+ (new String[] {}) : projection);
final int match = URI_MATCHER.match(uri);
switch (match) {
case URI_COMPLETE_CONVERSATIONS:
+ if (selectionBySubIds == null) {
+ // No subscriptions associated with user, return empty cursor.
+ return emptyCursor;
+ }
+ selection = DatabaseUtils.concatenateWhere(selection, selectionBySubIds);
+
cursor = getCompleteConversations(projection, selection, sortOrder, smsTable,
pduTable);
break;
@@ -374,11 +398,23 @@
cursor = getSimpleConversations(
projection, selection, selectionArgs, sortOrder);
} else {
+ if (selectionBySubIds == null) {
+ // No subscriptions associated with user, return empty cursor.
+ return emptyCursor;
+ }
+ selection = DatabaseUtils.concatenateWhere(selection, selectionBySubIds);
+
cursor = getConversations(
projection, selection, sortOrder, smsTable, pduTable);
}
break;
case URI_CONVERSATIONS_MESSAGES:
+ if (selectionBySubIds == null) {
+ // No subscriptions associated with user, return empty cursor.
+ return emptyCursor;
+ }
+ selection = DatabaseUtils.concatenateWhere(selection, selectionBySubIds);
+
cursor = getConversationMessages(uri.getPathSegments().get(1), projection,
selection, sortOrder, smsTable, pduTable);
break;
@@ -393,6 +429,12 @@
selectionArgs, sortOrder);
break;
case URI_MESSAGES_BY_PHONE:
+ if (selectionBySubIds == null) {
+ // No subscriptions associated with user, return emptyCursor.
+ return emptyCursor;
+ }
+ selection = DatabaseUtils.concatenateWhere(selection, selectionBySubIds);
+
cursor = getMessagesByPhoneNumber(
uri.getPathSegments().get(2), projection, selection, sortOrder, smsTable,
pduTable);
@@ -507,6 +549,14 @@
break;
}
}
+ if (selectionBySubIds == null) {
+ // No subscriptions associated with user, return empty cursor.
+ return emptyCursor;
+ }
+ // In PendingMessages table, SUBSCRIPTION_ID column name is pending_sub_id.
+ selectionBySubIds = "pending_" + selectionBySubIds;
+ selection = DatabaseUtils.concatenateWhere(selection, selectionBySubIds);
+
String finalSelection = TextUtils.isEmpty(selection)
? extraSelection : ("(" + extraSelection + ") AND " + selection);
String finalOrder = TextUtils.isEmpty(sortOrder)
@@ -516,11 +566,23 @@
break;
}
case URI_UNDELIVERED_MSG: {
+ if (selectionBySubIds == null) {
+ // No subscriptions associated with user, return empty cursor.
+ return emptyCursor;
+ }
+ selection = DatabaseUtils.concatenateWhere(selection, selectionBySubIds);
+
cursor = getUndeliveredMessages(projection, selection,
selectionArgs, sortOrder, smsTable, pduTable);
break;
}
case URI_DRAFT: {
+ if (selectionBySubIds == null) {
+ // No subscriptions associated with user, return empty cursor.
+ return emptyCursor;
+ }
+ selection = DatabaseUtils.concatenateWhere(selection, selectionBySubIds);
+
cursor = getDraftThread(projection, selection, sortOrder, smsTable, pduTable);
break;
}
@@ -532,11 +594,25 @@
Log.e(LOG_TAG, "Thread ID must be a long.");
break;
}
- cursor = getFirstLockedMessage(projection, "thread_id=" + Long.toString(threadId),
- sortOrder, smsTable, pduTable);
+ selection = DatabaseUtils.concatenateWhere(selection, ("thread_id=" + threadId));
+
+ if (selectionBySubIds == null) {
+ // No subscriptions associated with user, return empty cursor.
+ return emptyCursor;
+ }
+ selection = DatabaseUtils.concatenateWhere(selection, selectionBySubIds);
+
+ cursor = getFirstLockedMessage(projection, selection, sortOrder,
+ smsTable, pduTable);
break;
}
case URI_FIRST_LOCKED_MESSAGE_ALL: {
+ if (selectionBySubIds == null) {
+ // No subscriptions associated with user, return empty cursor.
+ return emptyCursor;
+ }
+ selection = DatabaseUtils.concatenateWhere(selection, selectionBySubIds);
+
cursor = getFirstLockedMessage(
projection, selection, sortOrder, smsTable, pduTable);
break;
@@ -1260,6 +1336,16 @@
@Override
public int delete(Uri uri, String selection,
String[] selectionArgs) {
+ final UserHandle callerUserHandle = Binder.getCallingUserHandle();
+ String selectionBySubIds;
+ final long token = Binder.clearCallingIdentity();
+ try {
+ // Filter MMS/SMS based on subId
+ selectionBySubIds = ProviderUtil.getSelectionBySubIds(getContext(), callerUserHandle);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
Context context = getContext();
int affectedRows = 0;
@@ -1273,10 +1359,23 @@
Log.e(LOG_TAG, "Thread ID must be a long.");
break;
}
+
+ if (selectionBySubIds == null) {
+ // No subscriptions associated with user, return 0.
+ return 0;
+ }
+ selection = DatabaseUtils.concatenateWhere(selectionBySubIds, selection);
+
affectedRows = deleteConversation(uri, selection, selectionArgs);
MmsSmsDatabaseHelper.updateThread(db, threadId);
break;
case URI_CONVERSATIONS:
+ if (selectionBySubIds == null) {
+ // No subscriptions associated with user, return 0.
+ return 0;
+ }
+ selection = DatabaseUtils.concatenateWhere(selectionBySubIds, selection);
+
affectedRows = MmsProvider.deleteMessages(context, db,
selection, selectionArgs, uri)
+ db.delete("sms", selection, selectionArgs);
@@ -1316,10 +1415,26 @@
@Override
public Uri insert(Uri uri, ContentValues values) {
+ final UserHandle callerUserHandle = Binder.getCallingUserHandle();
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
int matchIndex = URI_MATCHER.match(uri);
if (matchIndex == URI_PENDING_MSG) {
+ int subId;
+ if (values.containsKey(PendingMessages.SUBSCRIPTION_ID)) {
+ subId = values.getAsInteger(PendingMessages.SUBSCRIPTION_ID);
+ } else {
+ subId = SmsManager.getDefaultSmsSubscriptionId();
+ if (SubscriptionManager.isValidSubscriptionId(subId)) {
+ values.put(PendingMessages.SUBSCRIPTION_ID, subId);
+ }
+ }
+ if (!TelephonyPermissions
+ .checkSubscriptionAssociatedWithUser(getContext(), subId, callerUserHandle)) {
+ // TODO(b/258629881): Display error dialog.
+ return null;
+ }
+
long rowId = db.insert(TABLE_PENDING_MSG, null, values);
return uri.buildUpon().appendPath(Long.toString(rowId)).build();
} else if (matchIndex == URI_CANONICAL_ADDRESS) {
@@ -1333,17 +1448,42 @@
public int update(Uri uri, ContentValues values,
String selection, String[] selectionArgs) {
final int callerUid = Binder.getCallingUid();
+ final UserHandle callerUserHandle = Binder.getCallingUserHandle();
final String callerPkg = getCallingPackage();
+
+ String selectionBySubIds;
+ final long token = Binder.clearCallingIdentity();
+ try {
+ // Filter MMS/SMS based on subId.
+ selectionBySubIds = ProviderUtil.getSelectionBySubIds(getContext(), callerUserHandle);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
int affectedRows = 0;
switch(URI_MATCHER.match(uri)) {
case URI_CONVERSATIONS_MESSAGES:
+ if (selectionBySubIds == null) {
+ // No subscriptions associated with user, return 0.
+ return 0;
+ }
+ selection = DatabaseUtils.concatenateWhere(selection, selectionBySubIds);
+
String threadIdString = uri.getPathSegments().get(1);
affectedRows = updateConversation(threadIdString, values,
selection, selectionArgs, callerUid, callerPkg);
break;
case URI_PENDING_MSG:
+ if (selectionBySubIds == null) {
+ // No subscriptions associated with user, return 0.
+ return 0;
+ }
+ // In PendingMessages table, SUBSCRIPTION_ID column name is pending_sub_id.
+ selectionBySubIds = "pending_" + selectionBySubIds;
+ selection = DatabaseUtils.concatenateWhere(selection, selectionBySubIds);
+
affectedRows = db.update(TABLE_PENDING_MSG, values, selection, null);
break;
diff --git a/src/com/android/providers/telephony/ProviderUtil.java b/src/com/android/providers/telephony/ProviderUtil.java
index cd0f351..ea95f6e 100644
--- a/src/com/android/providers/telephony/ProviderUtil.java
+++ b/src/com/android/providers/telephony/ProviderUtil.java
@@ -16,18 +16,29 @@
package com.android.providers.telephony;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
+import android.os.Binder;
import android.os.Process;
+import android.os.UserHandle;
+import android.os.UserManager;
import android.provider.Telephony;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
import android.text.TextUtils;
import android.util.Log;
import com.android.internal.telephony.SmsApplication;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
/**
* Helpers
*/
@@ -126,4 +137,44 @@
}
return context.createDeviceProtectedStorageContext();
}
+
+ /**
+ * Get subscriptions associated with the user in the format of a selection string.
+ * @param context context
+ * @param userHandle caller user handle.
+ * @return subscriptions associated with the user in the format of a selection string
+ * or {@code null} if user is not associated with any subscription.
+ */
+ @Nullable
+ public static String getSelectionBySubIds(Context context, @NonNull UserHandle userHandle) {
+ List<SubscriptionInfo> associatedSubscriptionsList = new ArrayList<>();
+ SubscriptionManager subManager = context.getSystemService(SubscriptionManager.class);
+ if (subManager != null) {
+ // Get list of subscriptions associated with this user.
+ associatedSubscriptionsList = subManager
+ .getSubscriptionInfoListAssociatedWithUser(userHandle);
+ }
+
+ UserManager userManager = context.getSystemService(UserManager.class);
+ if ((userManager != null) && (!userManager.isManagedProfile(userHandle.getIdentifier()))) {
+ // SMS/MMS restored from another device have sub_id=-1.
+ // To query/update/delete those messages, sub_id=-1 should be in the selection string.
+ SubscriptionInfo invalidSubInfo = new SubscriptionInfo.Builder()
+ .setId(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
+ .build();
+ associatedSubscriptionsList.add(invalidSubInfo);
+ }
+
+ if (associatedSubscriptionsList.isEmpty()) {
+ return null;
+ }
+
+ // Converts [1,2,3,4,-1] to "'1','2','3','4','-1'" so that it can be appended to
+ // selection string
+ String subIdListStr = associatedSubscriptionsList.stream()
+ .map(subInfo -> ("'" + subInfo.getSubscriptionId() + "'"))
+ .collect(Collectors.joining(","));
+ return (Telephony.Sms.SUBSCRIPTION_ID + " IN (" + subIdListStr + ")");
+ }
+
}
diff --git a/src/com/android/providers/telephony/SmsProvider.java b/src/com/android/providers/telephony/SmsProvider.java
index d378c64..febe3a4 100644
--- a/src/com/android/providers/telephony/SmsProvider.java
+++ b/src/com/android/providers/telephony/SmsProvider.java
@@ -44,6 +44,7 @@
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.TelephonyPermissions;
import java.util.HashMap;
import java.util.List;
@@ -117,12 +118,15 @@
@Override
public Cursor query(Uri url, String[] projectionIn, String selection,
String[] selectionArgs, String sort) {
+ final int callingUid = Binder.getCallingUid();
+ final UserHandle callerUserHandle = Binder.getCallingUserHandle();
+
// First check if a restricted view of the "sms" table should be used based on the
// caller's identity. Only system, phone or the default sms app can have full access
// of sms data. For other apps, we present a restricted view which only contains sent
// or received messages.
final boolean accessRestricted = ProviderUtil.isAccessRestricted(
- getContext(), getCallingPackage(), Binder.getCallingUid());
+ getContext(), getCallingPackage(), callingUid);
final String smsTable = getSmsTable(accessRestricted);
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
@@ -136,6 +140,10 @@
}
}
+ Cursor emptyCursor = new MatrixCursor((projectionIn == null) ?
+ (new String[] {}) : projectionIn);
+
+
// Generate the body of the query.
int match = sURLMatcher.match(url);
SQLiteDatabase db = getReadableDatabase(match);
@@ -271,6 +279,13 @@
throw new IllegalArgumentException("Wrong path segements, uri= " + url);
}
}
+
+ if (!TelephonyPermissions.checkSubscriptionAssociatedWithUser(getContext(),
+ subId, callerUserHandle)) {
+ // If subId is not associated with user, return empty cursor.
+ return emptyCursor;
+ }
+
Cursor ret = getAllMessagesFromIcc(subId);
ret.setNotificationUri(getContext().getContentResolver(),
match == SMS_ALL_ICC ? ICC_URI : ICC_SUBID_URI);
@@ -293,6 +308,13 @@
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Wrong path segements, uri= " + url);
}
+
+ if (!TelephonyPermissions.checkSubscriptionAssociatedWithUser(getContext(),
+ subId, callerUserHandle)) {
+ // If subId is not associated with user, return empty cursor.
+ return emptyCursor;
+ }
+
Cursor ret = getSingleMessageFromIcc(subId, messageIndex);
ret.setNotificationUri(getContext().getContentResolver(),
match == SMS_ICC ? ICC_URI : ICC_SUBID_URI);
@@ -304,6 +326,23 @@
return null;
}
+ if (qb.getTables().equals(smsTable)) {
+ final long token = Binder.clearCallingIdentity();
+ String selectionBySubIds;
+ try {
+ // Filter SMS based on subId.
+ selectionBySubIds = ProviderUtil.getSelectionBySubIds(getContext(),
+ callerUserHandle);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ if (selectionBySubIds == null) {
+ // No subscriptions associated with user, return empty cursor.
+ return emptyCursor;
+ }
+ selection = DatabaseUtils.concatenateWhere(selection, selectionBySubIds);
+ }
+
String orderBy = null;
if (!TextUtils.isEmpty(sort)) {
@@ -314,7 +353,6 @@
Cursor ret = qb.query(db, projectionIn, selection, selectionArgs,
null, null, orderBy);
-
// TODO: Since the URLs are a mess, always use content://sms
ret.setNotificationUri(getContext().getContentResolver(),
NOTIFICATION_URI);
@@ -510,12 +548,14 @@
@Override
public int bulkInsert(@NonNull Uri url, @NonNull ContentValues[] values) {
final int callerUid = Binder.getCallingUid();
+ final UserHandle callerUserHandle = Binder.getCallingUserHandle();
final String callerPkg = getCallingPackage();
long token = Binder.clearCallingIdentity();
try {
int messagesInserted = 0;
for (ContentValues initialValues : values) {
- Uri insertUri = insertInner(url, initialValues, callerUid, callerPkg);
+ Uri insertUri = insertInner(url, initialValues, callerUid, callerPkg,
+ callerUserHandle);
if (insertUri != null) {
messagesInserted++;
}
@@ -535,10 +575,11 @@
@Override
public Uri insert(Uri url, ContentValues initialValues) {
final int callerUid = Binder.getCallingUid();
+ final UserHandle callerUserHandle = Binder.getCallingUserHandle();
final String callerPkg = getCallingPackage();
long token = Binder.clearCallingIdentity();
try {
- Uri insertUri = insertInner(url, initialValues, callerUid, callerPkg);
+ Uri insertUri = insertInner(url, initialValues, callerUid, callerPkg, callerUserHandle);
int match = sURLMatcher.match(url);
// Skip notifyChange() if insertUri is null for SMS_ALL_ICC or SMS_ALL_ICC_SUBID caused
@@ -556,7 +597,8 @@
}
}
- private Uri insertInner(Uri url, ContentValues initialValues, int callerUid, String callerPkg) {
+ private Uri insertInner(Uri url, ContentValues initialValues, int callerUid, String callerPkg,
+ UserHandle callerUserHandle) {
ContentValues values;
long rowID;
int type = Sms.MESSAGE_TYPE_ALL;
@@ -629,6 +671,12 @@
}
}
+ if (!TelephonyPermissions.checkSubscriptionAssociatedWithUser(getContext(), subId,
+ callerUserHandle)) {
+ // TODO(b/258629881): Display error dialog.
+ return null;
+ }
+
if (initialValues == null) {
throw new IllegalArgumentException("ContentValues is null");
}
@@ -755,6 +803,22 @@
}
}
+ if (table.equals(TABLE_SMS)) {
+ int subId;
+ if (values.containsKey(Telephony.Sms.SUBSCRIPTION_ID)) {
+ subId = values.getAsInteger(Telephony.Sms.SUBSCRIPTION_ID);
+ } else {
+ subId = SmsManager.getDefaultSmsSubscriptionId();
+ if (SubscriptionManager.isValidSubscriptionId(subId)) {
+ values.put(Telephony.Sms.SUBSCRIPTION_ID, subId);
+ }
+ }
+ if (!TelephonyPermissions
+ .checkSubscriptionAssociatedWithUser(getContext(), subId, callerUserHandle)) {
+ // TODO(b/258629881): Display error dialog.
+ }
+ }
+
rowID = db.insert(table, "body", values);
// Don't use a trigger for updating the words table because of a bug
@@ -848,12 +912,27 @@
@Override
public int delete(Uri url, String where, String[] whereArgs) {
+ final UserHandle callerUserHandle = Binder.getCallingUserHandle();
+ final long token = Binder.clearCallingIdentity();
+ String selectionBySubIds;
+ try {
+ // Filter SMS based on subId.
+ selectionBySubIds = ProviderUtil.getSelectionBySubIds(getContext(), callerUserHandle);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+
int count;
int match = sURLMatcher.match(url);
SQLiteDatabase db = getWritableDatabase(match);
boolean notifyIfNotDefault = true;
switch (match) {
case SMS_ALL:
+ if (selectionBySubIds == null) {
+ // No subscriptions associated with user, return 0.
+ return 0;
+ }
+ where = DatabaseUtils.concatenateWhere(where, selectionBySubIds);
count = db.delete(TABLE_SMS, where, whereArgs);
if (count != 0) {
// Don't update threads unless something changed.
@@ -884,6 +963,11 @@
// delete the messages from the sms table
where = DatabaseUtils.concatenateWhere("thread_id=" + threadID, where);
+ if (selectionBySubIds == null) {
+ // No subscriptions associated with user, return 0.
+ return 0;
+ }
+ where = DatabaseUtils.concatenateWhere(where, selectionBySubIds);
count = db.delete(TABLE_SMS, where, whereArgs);
MmsSmsDatabaseHelper.updateThread(db, threadID);
break;
@@ -924,6 +1008,13 @@
throw new IllegalArgumentException("Wrong path segements, uri= " + url);
}
}
+
+ if (!TelephonyPermissions.checkSubscriptionAssociatedWithUser(getContext(),
+ subId, callerUserHandle)) {
+ // If subId is not associated with user, return 0.
+ return 0;
+ }
+
deletedCnt = deleteAllMessagesFromIcc(subId);
// Notify changes even failure case since there might be some changes should be
// known.
@@ -954,6 +1045,13 @@
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Wrong path segements, uri= " + url);
}
+
+ if (!TelephonyPermissions.checkSubscriptionAssociatedWithUser(getContext(),
+ subId, callerUserHandle)) {
+ // If subId is not associated with user, return 0.
+ return 0;
+ }
+
success = deleteMessageFromIcc(subId, messageIndex);
// Notify changes even failure case since there might be some changes should be
// known.
@@ -1034,6 +1132,7 @@
@Override
public int update(Uri url, ContentValues values, String where, String[] whereArgs) {
final int callerUid = Binder.getCallingUid();
+ final UserHandle callerUserHandle = Binder.getCallingUserHandle();
final String callerPkg = getCallingPackage();
int count = 0;
String table = TABLE_SMS;
@@ -1103,6 +1202,23 @@
values.remove(Sms.CREATOR);
}
+ if (table.equals(TABLE_SMS)) {
+ final long token = Binder.clearCallingIdentity();
+ String selectionBySubIds;
+ try {
+ // Filter SMS based on subId.
+ selectionBySubIds = ProviderUtil.getSelectionBySubIds(getContext(),
+ callerUserHandle);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ if (selectionBySubIds == null) {
+ // No subscriptions associated with user, return 0;
+ return 0;
+ }
+ where = DatabaseUtils.concatenateWhere(where, selectionBySubIds);
+ }
+
where = DatabaseUtils.concatenateWhere(where, extraWhere);
count = db.update(table, values, where, whereArgs);
diff --git a/src/com/android/providers/telephony/TelephonyProvider.java b/src/com/android/providers/telephony/TelephonyProvider.java
index c6c0032..63973a8 100644
--- a/src/com/android/providers/telephony/TelephonyProvider.java
+++ b/src/com/android/providers/telephony/TelephonyProvider.java
@@ -161,7 +161,7 @@
private static final boolean DBG = true;
private static final boolean VDBG = false; // STOPSHIP if true
- private static final int DATABASE_VERSION = 60 << 16;
+ private static final int DATABASE_VERSION = 62 << 16;
private static final int URL_UNKNOWN = 0;
private static final int URL_TELEPHONY = 1;
private static final int URL_CURRENT = 2;
@@ -587,7 +587,9 @@
+ SubscriptionManager.USAGE_SETTING_UNKNOWN + ","
+ Telephony.SimInfo.COLUMN_TP_MESSAGE_REF +
" INTEGER DEFAULT -1,"
- + Telephony.SimInfo.COLUMN_USER_HANDLE + " INTEGER DEFAULT -1"
+ + Telephony.SimInfo.COLUMN_USER_HANDLE + " INTEGER DEFAULT "
+ + UserHandle.USER_NULL + ","
+ + Telephony.SimInfo.COLUMN_SATELLITE_ENABLED + " INTEGER DEFAULT -1"
+ ");";
}
@@ -1835,7 +1837,7 @@
// Try to update the siminfo table with new columns.
db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
+ Telephony.SimInfo.COLUMN_USER_HANDLE
- + " INTEGER DEFAULT -1;");
+ + " INTEGER DEFAULT " + UserHandle.USER_NULL +";");
} catch (SQLiteException e) {
if (DBG) {
log("onUpgrade failed to update " + SIMINFO_TABLE
@@ -1873,6 +1875,36 @@
}
oldVersion = 60 << 16 | 6;
}
+
+ if (oldVersion < (61 << 16 | 6)) {
+ try {
+ // If default value of USER_HANDLE column is set to -1, then update it to -10000
+ db.execSQL("UPDATE " + SIMINFO_TABLE + " SET "
+ + Telephony.SimInfo.COLUMN_USER_HANDLE + "=" + UserHandle.USER_NULL
+ + " WHERE " + Telephony.SimInfo.COLUMN_USER_HANDLE + "=-1;");
+ } catch (SQLiteException e) {
+ if (DBG) {
+ log("onUpgrade failed to update " + SIMINFO_TABLE
+ + " to add message Reference. ");
+ }
+ }
+ oldVersion = 61 << 16 | 6;
+ }
+
+ if (oldVersion < (62 << 16 | 6)) {
+ try {
+ // Try to update the siminfo table with new columns.
+ db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
+ + Telephony.SimInfo.COLUMN_SATELLITE_ENABLED
+ + " INTEGER DEFAULT -1;");
+ } catch (SQLiteException e) {
+ if (DBG) {
+ log("onUpgrade failed to update " + SIMINFO_TABLE
+ + " to add satellite enabled. ");
+ }
+ }
+ oldVersion = 62 << 16 | 6;
+ }
if (DBG) {
log("dbh.onUpgrade:- db=" + db + " oldV=" + oldVersion + " newV=" + newVersion);
}
@@ -3699,7 +3731,7 @@
PersistableBundle backedUpSimInfoEntry, int backupDataFormatVersion,
String isoCountryCodeFromDb,
List<String> wfcRestoreBlockedCountries) {
- if (DATABASE_VERSION != 60 << 16) {
+ if (DATABASE_VERSION != 62 << 16) {
throw new AssertionError("The database schema has been updated which might make "
+ "the format of #BACKED_UP_SIM_SPECIFIC_SETTINGS_FILE outdated. Make sure to "
+ "1) review whether any of the columns in #SIM_INFO_COLUMNS_TO_BACKUP have "
@@ -5534,8 +5566,10 @@
if (overrideRule != null) {
ContentValues cv = new ContentValues(1);
- cv.put(Telephony.SimInfo.COLUMN_ENABLED_MOBILE_DATA_POLICIES,
- convertFromOverrideRuleLegacy(overrideRule));
+ // convert override rule to its corresponding mobile data policy
+ overrideRule = overrideRule.contains("mms") ?
+ String.valueOf(TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED): "";
+ cv.put(Telephony.SimInfo.COLUMN_ENABLED_MOBILE_DATA_POLICIES, overrideRule);
db.update(SIMINFO_TABLE, cv,
Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID + "=?",
new String[]{subId});
@@ -5543,26 +5577,6 @@
}
/**
- * Convert legacy override rule retrieved from Telephony database to mobile data policy.
- *
- * @param rules String legacy override rule retrieved from Telephony database.
- * @return The corresponding mobile data policy.
- */
- private static String convertFromOverrideRuleLegacy(@NonNull String rules) {
- if (TextUtils.isEmpty(rules)) return null;
- String policies = "";
- if (rules.contains("mms")) {
- policies += String.valueOf(TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED);
- }
- if (rules.contains("*")) {
- if (policies.length() != 0) policies += ",";
- policies += String.valueOf(
- TelephonyManager.MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL);
- }
- return policies;
- }
-
- /**
* Dump the database table.
*
* @param tableName Table name.
diff --git a/tests/Android.bp b/tests/Android.bp
index 7695c03..0945bfa 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -10,6 +10,7 @@
"compatibility-device-util-axt",
"androidx.test.rules",
"truth-prebuilt",
+ "androidx.test.core",
],
libs: [
"android.test.runner",
diff --git a/tests/src/com/android/providers/telephony/ProviderUtilTest.java b/tests/src/com/android/providers/telephony/ProviderUtilTest.java
new file mode 100644
index 0000000..9d8532e
--- /dev/null
+++ b/tests/src/com/android/providers/telephony/ProviderUtilTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.providers.telephony;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.UserHandle;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ProviderUtilTest {
+ private static final String TAG = "ProviderUtilTest";
+
+ private Context mContext;
+ @Mock
+ private SubscriptionManager mSubscriptionManager;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(ApplicationProvider.getApplicationContext());
+
+ when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ @Test
+ public void getSelectionBySubIds_noSubscription() {
+ List<SubscriptionInfo> subscriptionInfoList = new ArrayList<>();
+ doReturn(subscriptionInfoList).when(mSubscriptionManager)
+ .getSubscriptionInfoListAssociatedWithUser(UserHandle.SYSTEM);
+
+ assertThat(ProviderUtil.getSelectionBySubIds(mContext, UserHandle.SYSTEM))
+ .isEqualTo("sub_id IN ('-1')");
+ }
+
+ @Test
+ public void getSelectionBySubIds_withDefaultSubId() {
+ // As sub_id is not set explicitly, its value will be -1
+ SubscriptionInfo subscriptionInfo1 = new SubscriptionInfo.Builder()
+ .setSimSlotIndex(0)
+ .build();
+ List<SubscriptionInfo> subscriptionInfoList = new ArrayList<>();
+ subscriptionInfoList.add(subscriptionInfo1);
+
+ doReturn(subscriptionInfoList).when(mSubscriptionManager)
+ .getSubscriptionInfoListAssociatedWithUser(UserHandle.SYSTEM);
+ assertThat(ProviderUtil.getSelectionBySubIds(mContext, UserHandle.SYSTEM))
+ .isEqualTo("sub_id IN ('-1','-1')");
+ }
+
+ @Test
+ public void getSelectionBySubIds_withActiveSubscriptions() {
+ SubscriptionInfo subscriptionInfo1 = new SubscriptionInfo.Builder()
+ .setId(1)
+ .setSimSlotIndex(0)
+ .build();
+ List<SubscriptionInfo> subscriptionInfoList = new ArrayList<>();
+
+ SubscriptionInfo subscriptionInfo2 = new SubscriptionInfo.Builder()
+ .setId(2)
+ .setSimSlotIndex(1)
+ .build();
+
+ subscriptionInfoList.add(subscriptionInfo1);
+ subscriptionInfoList.add(subscriptionInfo2);
+ doReturn(subscriptionInfoList).when(mSubscriptionManager)
+ .getSubscriptionInfoListAssociatedWithUser(UserHandle.SYSTEM);
+
+ assertThat(ProviderUtil.getSelectionBySubIds(mContext, UserHandle.SYSTEM))
+ .isEqualTo("sub_id IN ('1','2','-1')");
+ }
+}
\ No newline at end of file
diff --git a/tests/src/com/android/providers/telephony/TelephonyDatabaseHelperTest.java b/tests/src/com/android/providers/telephony/TelephonyDatabaseHelperTest.java
index 5b54f04..26a3a46 100644
--- a/tests/src/com/android/providers/telephony/TelephonyDatabaseHelperTest.java
+++ b/tests/src/com/android/providers/telephony/TelephonyDatabaseHelperTest.java
@@ -19,12 +19,16 @@
import static android.provider.Telephony.Carriers;
import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
+import android.os.UserHandle;
import android.provider.Telephony;
import android.telephony.SubscriptionManager;
import android.text.TextUtils;
@@ -402,6 +406,76 @@
Telephony.SimInfo.COLUMN_USER_HANDLE));
}
+ @Test
+ public void databaseHelperOnUpgrade_hasUserHandleField_updateNullUserHandleValue() {
+ Log.d(TAG, "databaseHelperOnUpgrade_hasUserHandleField_updateNullUserHandleValue");
+ // (5 << 16 | 6) is the first upgrade trigger in onUpgrade
+ SQLiteDatabase db = mInMemoryDbHelper.getWritableDatabase();
+ // UserHandle column is added in version 59 .
+ mHelper.onUpgrade(db, (4 << 16), 59);
+
+ // The upgraded db must have Telephony.SimInfo.COLUMN_USER_HANDLE.
+ Cursor cursor = db.query("siminfo", null, null, null,
+ null, null, null);
+ String[] upgradedColumns = cursor.getColumnNames();
+ Log.d(TAG, "siminfo columns: " + Arrays.toString(upgradedColumns));
+ assertTrue(Arrays.asList(upgradedColumns).contains(Telephony.SimInfo.COLUMN_USER_HANDLE));
+
+ // Insert test contentValues into db.
+ final int insertSubId = 11;
+ ContentValues contentValues = new ContentValues();
+ // Set userHandle=-1
+ contentValues.put(Telephony.SimInfo.COLUMN_USER_HANDLE, -1);
+ contentValues.put(Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID, insertSubId);
+ // Populate NON NULL columns.
+ contentValues.put(Telephony.SimInfo.COLUMN_ICC_ID, "123");
+ contentValues.put(Telephony.SimInfo.COLUMN_DISPLAY_NUMBER_FORMAT, 0);
+ contentValues.put(Telephony.SimInfo.COLUMN_CARD_ID, "123");
+ db.insert("siminfo", null, contentValues);
+
+ // Query UserHandle value from db which should be equal to -1.
+ final String[] testProjection = {Telephony.SimInfo.COLUMN_USER_HANDLE};
+ final String selection = Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID + "=?";
+ String[] selectionArgs = { Integer.toString(insertSubId) };
+ cursor = db.query("siminfo", testProjection, selection, selectionArgs,
+ null, null, null);
+ assertNotNull(cursor);
+ assertEquals(1, cursor.getCount());
+ cursor.moveToFirst();
+ int userHandleVal = cursor.getInt(0);
+ assertEquals(-1, userHandleVal);
+
+ // Upgrade db from version 59 to version 61.
+ mHelper.onUpgrade(db, (59 << 16), 61);
+
+ // Query userHandle value from db which should be equal to UserHandle.USER_NULL(-10000)
+ // after db upgrade.
+ cursor = db.query("siminfo", testProjection, selection, selectionArgs,
+ null, null, null);
+ assertNotNull(cursor);
+ assertEquals(1, cursor.getCount());
+ cursor.moveToFirst();
+ userHandleVal = cursor.getInt(0);
+ assertEquals(UserHandle.USER_NULL, userHandleVal);
+ }
+
+ @Test
+ public void databaseHelperOnUpgrade_hasSatelliteEnabledField() {
+ Log.d(TAG, "databaseHelperOnUpgrade_hasSatelliteEnabledField");
+ // (5 << 16 | 6) is the first upgrade trigger in onUpgrade
+ SQLiteDatabase db = mInMemoryDbHelper.getWritableDatabase();
+ mHelper.onUpgrade(db, (4 << 16), TelephonyProvider.getVersion(mContext));
+
+ // the upgraded db must have
+ // Telephony.SimInfo.COLUMN_SATELLITE_ENABLED
+ Cursor cursor = db.query("siminfo", null, null, null, null, null, null);
+ String[] upgradedColumns = cursor.getColumnNames();
+ Log.d(TAG, "siminfo columns: " + Arrays.toString(upgradedColumns));
+
+ assertTrue(Arrays.asList(upgradedColumns).contains(
+ Telephony.SimInfo.COLUMN_SATELLITE_ENABLED));
+ }
+
/**
* Helper for an in memory DB used to test the TelephonyProvider#DatabaseHelper.
*
diff --git a/tests/src/com/android/providers/telephony/TelephonyProviderTest.java b/tests/src/com/android/providers/telephony/TelephonyProviderTest.java
index 7b74f9d..de4c6c5 100644
--- a/tests/src/com/android/providers/telephony/TelephonyProviderTest.java
+++ b/tests/src/com/android/providers/telephony/TelephonyProviderTest.java
@@ -717,6 +717,7 @@
final int insertProfileClass = SubscriptionManager.PROFILE_CLASS_DEFAULT;
final int insertPortIndex = 1;
final int insertUserHandle = 0;
+ final int insertSatelliteEnabled = 1;
contentValues.put(SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID, insertSubId);
contentValues.put(SubscriptionManager.DISPLAY_NAME, insertDisplayName);
contentValues.put(SubscriptionManager.CARRIER_NAME, insertCarrierName);
@@ -725,6 +726,7 @@
contentValues.put(SubscriptionManager.PROFILE_CLASS, insertProfileClass);
contentValues.put(SubscriptionManager.PORT_INDEX, insertPortIndex);
contentValues.put(SubscriptionManager.USER_HANDLE, insertUserHandle);
+ contentValues.put(SubscriptionManager.SATELLITE_ENABLED, insertSatelliteEnabled);
Log.d(TAG, "testSimTable Inserting contentValues: " + contentValues);
mContentResolver.insert(SimInfo.CONTENT_URI, contentValues);
@@ -738,6 +740,7 @@
SubscriptionManager.PROFILE_CLASS,
SubscriptionManager.PORT_INDEX,
SubscriptionManager.USER_HANDLE,
+ SubscriptionManager.SATELLITE_ENABLED,
};
final String selection = SubscriptionManager.DISPLAY_NAME + "=?";
String[] selectionArgs = { insertDisplayName };
@@ -756,11 +759,13 @@
final int resultProfileClass = cursor.getInt(3);
final int resultPortIndex = cursor.getInt(4);
final int resultUserHandle = cursor.getInt(5);
+ final int resultSatelliteEnabled = cursor.getInt(6);
assertEquals(insertSubId, resultSubId);
assertEquals(insertCarrierName, resultCarrierName);
assertEquals(insertCardId, resultCardId);
assertEquals(insertPortIndex, resultPortIndex);
assertEquals(insertUserHandle, resultUserHandle);
+ assertEquals(insertSatelliteEnabled, resultSatelliteEnabled);
// delete test content
final String selectionToDelete = SubscriptionManager.DISPLAY_NAME + "=?";