mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2024-10-01 01:35:54 -04:00
15.1 November ASB work
Signed-off-by: Tad <tad@spotco.us>
This commit is contained in:
parent
ad298935a2
commit
5a87cd6bcb
79
Patches/LineageOS-15.1/android_frameworks_av/373949.patch
Normal file
79
Patches/LineageOS-15.1/android_frameworks_av/373949.patch
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Shruti Bihani <shrutibihani@google.com>
|
||||||
|
Date: Mon, 10 Jul 2023 08:53:42 +0000
|
||||||
|
Subject: [PATCH] Fix for heap buffer overflow issue flagged by fuzzer test.
|
||||||
|
|
||||||
|
OOB write occurs when a value is assigned to a buffer index which is greater than the buffer size. Adding a check on buffer bounds fixes the issue.
|
||||||
|
|
||||||
|
Similar checks have been added wherever applicable on other such methods of the class.
|
||||||
|
|
||||||
|
Bug: 243463593
|
||||||
|
Test: Build mtp_packet_fuzzer and run on the target device
|
||||||
|
(cherry picked from commit a669e34bb8e6f0f7b5d7a35144bd342271a24712)
|
||||||
|
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:1401a723899766632363129265b30d433ac69c44)
|
||||||
|
Merged-In: Icd0f2307803a1a35e655bc08d9d4cca5e2b58a9b
|
||||||
|
Change-Id: Icd0f2307803a1a35e655bc08d9d4cca5e2b58a9b
|
||||||
|
---
|
||||||
|
media/mtp/MtpPacket.cpp | 40 +++++++++++++++++++++++++++++++---------
|
||||||
|
1 file changed, 31 insertions(+), 9 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/media/mtp/MtpPacket.cpp b/media/mtp/MtpPacket.cpp
|
||||||
|
index 3dd4248e4c..917967cf17 100644
|
||||||
|
--- a/media/mtp/MtpPacket.cpp
|
||||||
|
+++ b/media/mtp/MtpPacket.cpp
|
||||||
|
@@ -92,24 +92,46 @@ void MtpPacket::copyFrom(const MtpPacket& src) {
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t MtpPacket::getUInt16(int offset) const {
|
||||||
|
- return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset];
|
||||||
|
+ if ((unsigned long)(offset+2) <= mBufferSize) {
|
||||||
|
+ return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset];
|
||||||
|
+ }
|
||||||
|
+ else {
|
||||||
|
+ ALOGE("offset for buffer read is greater than buffer size!");
|
||||||
|
+ abort();
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t MtpPacket::getUInt32(int offset) const {
|
||||||
|
- return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) |
|
||||||
|
- ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset];
|
||||||
|
+ if ((unsigned long)(offset+4) <= mBufferSize) {
|
||||||
|
+ return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) |
|
||||||
|
+ ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset];
|
||||||
|
+ }
|
||||||
|
+ else {
|
||||||
|
+ ALOGE("offset for buffer read is greater than buffer size!");
|
||||||
|
+ abort();
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
void MtpPacket::putUInt16(int offset, uint16_t value) {
|
||||||
|
- mBuffer[offset++] = (uint8_t)(value & 0xFF);
|
||||||
|
- mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF);
|
||||||
|
+ if ((unsigned long)(offset+2) <= mBufferSize) {
|
||||||
|
+ mBuffer[offset++] = (uint8_t)(value & 0xFF);
|
||||||
|
+ mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF);
|
||||||
|
+ }
|
||||||
|
+ else {
|
||||||
|
+ ALOGE("offset for buffer write is greater than buffer size!");
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
void MtpPacket::putUInt32(int offset, uint32_t value) {
|
||||||
|
- mBuffer[offset++] = (uint8_t)(value & 0xFF);
|
||||||
|
- mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF);
|
||||||
|
- mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF);
|
||||||
|
- mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF);
|
||||||
|
+ if ((unsigned long)(offset+4) <= mBufferSize) {
|
||||||
|
+ mBuffer[offset++] = (uint8_t)(value & 0xFF);
|
||||||
|
+ mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF);
|
||||||
|
+ mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF);
|
||||||
|
+ mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF);
|
||||||
|
+ }
|
||||||
|
+ else {
|
||||||
|
+ ALOGE("offset for buffer write is greater than buffer size!");
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t MtpPacket::getContainerCode() const {
|
31
Patches/LineageOS-15.1/android_frameworks_base/373953.patch
Normal file
31
Patches/LineageOS-15.1/android_frameworks_base/373953.patch
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: kumarashishg <kumarashishg@google.com>
|
||||||
|
Date: Thu, 3 Aug 2023 12:01:29 +0000
|
||||||
|
Subject: [PATCH] Use type safe API of readParcelableArray
|
||||||
|
|
||||||
|
Bug: 291299076
|
||||||
|
Test: Build and flash the device and check if it throws exception for
|
||||||
|
non UsbInterface object
|
||||||
|
Test: atest CtsUsbManagerTestCases
|
||||||
|
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:85d7e6712a9eeeed3bdd68ea3c3862c7e88bfe70)
|
||||||
|
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:60bfbde79f2ffb012abced55d358fdf6380c0bae)
|
||||||
|
Merged-In: I2917c8331b6d56caaa9a6479bcd9a2d089f5f503
|
||||||
|
Change-Id: I2917c8331b6d56caaa9a6479bcd9a2d089f5f503
|
||||||
|
---
|
||||||
|
core/java/android/hardware/usb/UsbConfiguration.java | 3 ++-
|
||||||
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/core/java/android/hardware/usb/UsbConfiguration.java b/core/java/android/hardware/usb/UsbConfiguration.java
|
||||||
|
index a17157087a61..b8f58ee68c42 100644
|
||||||
|
--- a/core/java/android/hardware/usb/UsbConfiguration.java
|
||||||
|
+++ b/core/java/android/hardware/usb/UsbConfiguration.java
|
||||||
|
@@ -160,7 +160,8 @@ public class UsbConfiguration implements Parcelable {
|
||||||
|
String name = in.readString();
|
||||||
|
int attributes = in.readInt();
|
||||||
|
int maxPower = in.readInt();
|
||||||
|
- Parcelable[] interfaces = in.readParcelableArray(UsbInterface.class.getClassLoader());
|
||||||
|
+ Parcelable[] interfaces = in.readParcelableArray(
|
||||||
|
+ UsbInterface.class.getClassLoader(), UsbInterface.class);
|
||||||
|
UsbConfiguration configuration = new UsbConfiguration(id, name, attributes, maxPower);
|
||||||
|
configuration.setInterfaces(interfaces);
|
||||||
|
return configuration;
|
68
Patches/LineageOS-15.1/android_frameworks_base/373955.patch
Normal file
68
Patches/LineageOS-15.1/android_frameworks_base/373955.patch
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Songchun Fan <schfan@google.com>
|
||||||
|
Date: Mon, 14 Aug 2023 15:24:11 -0700
|
||||||
|
Subject: [PATCH] verify ringtone URI before setting
|
||||||
|
|
||||||
|
Similar to ag/24422287, but the same URI verification should be done in
|
||||||
|
SettingsProvider as well, which can be called by apps via
|
||||||
|
Settings.System API or ContentProvider APIs without using
|
||||||
|
RingtoneManager.
|
||||||
|
|
||||||
|
BUG: 227201030
|
||||||
|
Test: manual with a test app. Will add a CTS test.
|
||||||
|
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:1b234678ec122994ccbfc52ac48aafdad7fdb1ed)
|
||||||
|
Merged-In: Ic0ffa1db14b5660d02880b632a7f2ad9e6e5d84b
|
||||||
|
Change-Id: Ic0ffa1db14b5660d02880b632a7f2ad9e6e5d84b
|
||||||
|
---
|
||||||
|
.../providers/settings/SettingsProvider.java | 31 +++++++++++++++++++
|
||||||
|
1 file changed, 31 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
|
||||||
|
index a3dc435e5371..a1c6c60a976d 100644
|
||||||
|
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
|
||||||
|
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
|
||||||
|
@@ -1407,6 +1407,9 @@ public class SettingsProvider extends ContentProvider {
|
||||||
|
cacheName = Settings.System.ALARM_ALERT_CACHE;
|
||||||
|
}
|
||||||
|
if (cacheName != null) {
|
||||||
|
+ if (!isValidAudioUri(name, value)) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
final File cacheFile = new File(
|
||||||
|
getRingtoneCacheDir(owningUserId), cacheName);
|
||||||
|
cacheFile.delete();
|
||||||
|
@@ -1439,6 +1442,34 @@ public class SettingsProvider extends ContentProvider {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ private boolean isValidAudioUri(String name, String uri) {
|
||||||
|
+ if (uri != null) {
|
||||||
|
+ Uri audioUri = Uri.parse(uri);
|
||||||
|
+ if (Settings.AUTHORITY.equals(
|
||||||
|
+ ContentProvider.getAuthorityWithoutUserId(audioUri.getAuthority()))) {
|
||||||
|
+ // Don't accept setting the default uri to self-referential URIs like
|
||||||
|
+ // Settings.System.DEFAULT_RINGTONE_URI, which is an alias to the value of this
|
||||||
|
+ // setting.
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+ final String mimeType = getContext().getContentResolver().getType(audioUri);
|
||||||
|
+ if (mimeType == null) {
|
||||||
|
+ Slog.e(LOG_TAG,
|
||||||
|
+ "mutateSystemSetting for setting: " + name + " URI: " + audioUri
|
||||||
|
+ + " ignored: failure to find mimeType (no access from this context?)");
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+ if (!(mimeType.startsWith("audio/") || mimeType.equals("application/ogg")
|
||||||
|
+ || mimeType.equals("application/x-flac"))) {
|
||||||
|
+ Slog.e(LOG_TAG,
|
||||||
|
+ "mutateSystemSetting for setting: " + name + " URI: " + audioUri
|
||||||
|
+ + " ignored: associated mimeType: " + mimeType + " is not an audio type");
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
private boolean hasWriteSecureSettingsPermission() {
|
||||||
|
// Write secure settings is a more protected permission. If caller has it we are good.
|
||||||
|
if (getContext().checkCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
|
@ -0,0 +1,816 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Aishwarya Mallampati <amallampati@google.com>
|
||||||
|
Date: Wed, 23 Aug 2023 18:30:46 +0000
|
||||||
|
Subject: [PATCH] DO NOT MERGE Block access to sms/mms db from work profile.
|
||||||
|
|
||||||
|
Bug: 289242655
|
||||||
|
Test: Manually verified work profile cannot access personal sms by
|
||||||
|
following steps mentioned in b/289242655#comment26
|
||||||
|
- atest SmsProviderTest
|
||||||
|
- atest MmsProviderTest
|
||||||
|
- atest SmsBackupRestoreTest
|
||||||
|
- QA performed regression testing and confirmed fix is working as intended here: b/294459052#comment30
|
||||||
|
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:950a7e5a4bf1b38e846fe00642105479efded57d)
|
||||||
|
Merged-In: Ib1c9ec75f77e8412b53df50f5414caa0e5aaa277
|
||||||
|
Change-Id: Ib1c9ec75f77e8412b53df50f5414caa0e5aaa277
|
||||||
|
---
|
||||||
|
.../providers/telephony/MmsProvider.java | 41 ++++-
|
||||||
|
.../telephony/MmsSmsDatabaseHelper.java | 156 +++++++++-------
|
||||||
|
.../providers/telephony/MmsSmsProvider.java | 36 ++++
|
||||||
|
.../providers/telephony/SmsProvider.java | 35 ++++
|
||||||
|
.../providers/telephony/MmsProviderTest.java | 173 ++++++++++++++++++
|
||||||
|
.../telephony/MmsProviderTestable.java | 77 ++++++++
|
||||||
|
.../providers/telephony/SmsProviderTest.java | 56 +++++-
|
||||||
|
7 files changed, 503 insertions(+), 71 deletions(-)
|
||||||
|
create mode 100644 tests/src/com/android/providers/telephony/MmsProviderTest.java
|
||||||
|
create mode 100644 tests/src/com/android/providers/telephony/MmsProviderTestable.java
|
||||||
|
|
||||||
|
diff --git a/src/com/android/providers/telephony/MmsProvider.java b/src/com/android/providers/telephony/MmsProvider.java
|
||||||
|
index aab61b80..f00fe508 100644
|
||||||
|
--- a/src/com/android/providers/telephony/MmsProvider.java
|
||||||
|
+++ b/src/com/android/providers/telephony/MmsProvider.java
|
||||||
|
@@ -24,6 +24,7 @@ import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.UriMatcher;
|
||||||
|
import android.database.Cursor;
|
||||||
|
+import android.database.MatrixCursor;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.database.sqlite.SQLiteException;
|
||||||
|
import android.database.sqlite.SQLiteOpenHelper;
|
||||||
|
@@ -33,6 +34,7 @@ import android.os.Binder;
|
||||||
|
import android.os.FileUtils;
|
||||||
|
import android.os.ParcelFileDescriptor;
|
||||||
|
import android.os.UserHandle;
|
||||||
|
+import android.os.UserManager;
|
||||||
|
import android.provider.BaseColumns;
|
||||||
|
import android.provider.Telephony;
|
||||||
|
import android.provider.Telephony.CanonicalAddressesColumns;
|
||||||
|
@@ -48,6 +50,8 @@ import android.text.TextUtils;
|
||||||
|
import android.util.EventLog;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
+import com.android.internal.annotations.VisibleForTesting;
|
||||||
|
+
|
||||||
|
import com.google.android.mms.pdu.PduHeaders;
|
||||||
|
import com.google.android.mms.util.DownloadDrmHelper;
|
||||||
|
|
||||||
|
@@ -92,6 +96,16 @@ public class MmsProvider extends ContentProvider {
|
||||||
|
@Override
|
||||||
|
public Cursor query(Uri uri, String[] projection,
|
||||||
|
String selection, String[] selectionArgs, String sortOrder) {
|
||||||
|
+ Cursor emptyCursor = new MatrixCursor((projection == null) ?
|
||||||
|
+ (new String[] {}) : projection);
|
||||||
|
+ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
|
||||||
|
+ if ((userManager != null) && (userManager.isManagedProfile(
|
||||||
|
+ Binder.getCallingUserHandle().getIdentifier()))) {
|
||||||
|
+ // If work profile is trying to query mms, return empty cursor.
|
||||||
|
+ Log.e(TAG, "Managed profile is not allowed to query MMS.");
|
||||||
|
+ return emptyCursor;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
// 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
|
||||||
|
@@ -305,6 +319,14 @@ public class MmsProvider extends ContentProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Uri insert(Uri uri, ContentValues values) {
|
||||||
|
+ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
|
||||||
|
+ if ((userManager != null) && (userManager.isManagedProfile(
|
||||||
|
+ Binder.getCallingUserHandle().getIdentifier()))) {
|
||||||
|
+ // If work profile is trying to insert mms, return null.
|
||||||
|
+ Log.e(TAG, "Managed profile is not allowed to insert MMS.");
|
||||||
|
+ return null;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
final int callerUid = Binder.getCallingUid();
|
||||||
|
final String callerPkg = getCallingPackage();
|
||||||
|
int msgBox = Mms.MESSAGE_BOX_ALL;
|
||||||
|
@@ -614,6 +636,14 @@ public class MmsProvider extends ContentProvider {
|
||||||
|
@Override
|
||||||
|
public int delete(Uri uri, String selection,
|
||||||
|
String[] selectionArgs) {
|
||||||
|
+ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
|
||||||
|
+ if ((userManager != null) && (userManager.isManagedProfile(
|
||||||
|
+ Binder.getCallingUserHandle().getIdentifier()))) {
|
||||||
|
+ // If work profile is trying to delete mms, return 0.
|
||||||
|
+ Log.e(TAG, "Managed profile is not allowed to delete MMS.");
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
int match = sURLMatcher.match(uri);
|
||||||
|
if (LOCAL_LOGV) {
|
||||||
|
Log.v(TAG, "Delete uri=" + uri + ", match=" + match);
|
||||||
|
@@ -766,6 +796,14 @@ public class MmsProvider extends ContentProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
|
||||||
|
+ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
|
||||||
|
+ if ((userManager != null) && (userManager.isManagedProfile(
|
||||||
|
+ Binder.getCallingUserHandle().getIdentifier()))) {
|
||||||
|
+ // If work profile is trying to update mms, return 0.
|
||||||
|
+ Log.e(TAG, "Managed profile is not allowed to update MMS.");
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
// The _data column is filled internally in MmsProvider, so this check is just to avoid
|
||||||
|
// it from being inadvertently set. This is not supposed to be a protection against
|
||||||
|
// malicious attack, since sql injection could still be attempted to bypass the check. On
|
||||||
|
@@ -1049,7 +1087,8 @@ public class MmsProvider extends ContentProvider {
|
||||||
|
sURLMatcher.addURI("mms", "resetFilePerm/*", MMS_PART_RESET_FILE_PERMISSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
- private SQLiteOpenHelper mOpenHelper;
|
||||||
|
+ @VisibleForTesting
|
||||||
|
+ public SQLiteOpenHelper mOpenHelper;
|
||||||
|
|
||||||
|
private static String concatSelections(String selection1, String selection2) {
|
||||||
|
if (TextUtils.isEmpty(selection1)) {
|
||||||
|
diff --git a/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java b/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
|
||||||
|
index 8b2c8397..9b7693fb 100644
|
||||||
|
--- a/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
|
||||||
|
+++ b/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
|
||||||
|
@@ -587,78 +587,96 @@ public class MmsSmsDatabaseHelper extends SQLiteOpenHelper {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ @VisibleForTesting
|
||||||
|
+ public static String CREATE_ADDR_TABLE_STR =
|
||||||
|
+ "CREATE TABLE " + MmsProvider.TABLE_ADDR + " (" +
|
||||||
|
+ Addr._ID + " INTEGER PRIMARY KEY," +
|
||||||
|
+ Addr.MSG_ID + " INTEGER," +
|
||||||
|
+ Addr.CONTACT_ID + " INTEGER," +
|
||||||
|
+ Addr.ADDRESS + " TEXT," +
|
||||||
|
+ Addr.TYPE + " INTEGER," +
|
||||||
|
+ Addr.CHARSET + " INTEGER);";
|
||||||
|
+
|
||||||
|
+ @VisibleForTesting
|
||||||
|
+ public static String CREATE_PART_TABLE_STR =
|
||||||
|
+ "CREATE TABLE " + MmsProvider.TABLE_PART + " (" +
|
||||||
|
+ Part._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
|
||||||
|
+ Part.MSG_ID + " INTEGER," +
|
||||||
|
+ Part.SEQ + " INTEGER DEFAULT 0," +
|
||||||
|
+ Part.CONTENT_TYPE + " TEXT," +
|
||||||
|
+ Part.NAME + " TEXT," +
|
||||||
|
+ Part.CHARSET + " INTEGER," +
|
||||||
|
+ Part.CONTENT_DISPOSITION + " TEXT," +
|
||||||
|
+ Part.FILENAME + " TEXT," +
|
||||||
|
+ Part.CONTENT_ID + " TEXT," +
|
||||||
|
+ Part.CONTENT_LOCATION + " TEXT," +
|
||||||
|
+ Part.CT_START + " INTEGER," +
|
||||||
|
+ Part.CT_TYPE + " TEXT," +
|
||||||
|
+ Part._DATA + " TEXT," +
|
||||||
|
+ Part.TEXT + " TEXT);";
|
||||||
|
+
|
||||||
|
+ public static String CREATE_PDU_TABLE_STR =
|
||||||
|
+ "CREATE TABLE " + MmsProvider.TABLE_PDU + " (" +
|
||||||
|
+ Mms._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
|
||||||
|
+ Mms.THREAD_ID + " INTEGER," +
|
||||||
|
+ Mms.DATE + " INTEGER," +
|
||||||
|
+ Mms.DATE_SENT + " INTEGER DEFAULT 0," +
|
||||||
|
+ Mms.MESSAGE_BOX + " INTEGER," +
|
||||||
|
+ Mms.READ + " INTEGER DEFAULT 0," +
|
||||||
|
+ Mms.MESSAGE_ID + " TEXT," +
|
||||||
|
+ Mms.SUBJECT + " TEXT," +
|
||||||
|
+ Mms.SUBJECT_CHARSET + " INTEGER," +
|
||||||
|
+ Mms.CONTENT_TYPE + " TEXT," +
|
||||||
|
+ Mms.CONTENT_LOCATION + " TEXT," +
|
||||||
|
+ Mms.EXPIRY + " INTEGER," +
|
||||||
|
+ Mms.MESSAGE_CLASS + " TEXT," +
|
||||||
|
+ Mms.MESSAGE_TYPE + " INTEGER," +
|
||||||
|
+ Mms.MMS_VERSION + " INTEGER," +
|
||||||
|
+ Mms.MESSAGE_SIZE + " INTEGER," +
|
||||||
|
+ Mms.PRIORITY + " INTEGER," +
|
||||||
|
+ Mms.READ_REPORT + " INTEGER," +
|
||||||
|
+ Mms.REPORT_ALLOWED + " INTEGER," +
|
||||||
|
+ Mms.RESPONSE_STATUS + " INTEGER," +
|
||||||
|
+ Mms.STATUS + " INTEGER," +
|
||||||
|
+ Mms.TRANSACTION_ID + " TEXT," +
|
||||||
|
+ Mms.RETRIEVE_STATUS + " INTEGER," +
|
||||||
|
+ Mms.RETRIEVE_TEXT + " TEXT," +
|
||||||
|
+ Mms.RETRIEVE_TEXT_CHARSET + " INTEGER," +
|
||||||
|
+ Mms.READ_STATUS + " INTEGER," +
|
||||||
|
+ Mms.CONTENT_CLASS + " INTEGER," +
|
||||||
|
+ Mms.RESPONSE_TEXT + " TEXT," +
|
||||||
|
+ Mms.DELIVERY_TIME + " INTEGER," +
|
||||||
|
+ Mms.DELIVERY_REPORT + " INTEGER," +
|
||||||
|
+ Mms.LOCKED + " INTEGER DEFAULT 0," +
|
||||||
|
+ Mms.SUBSCRIPTION_ID + " INTEGER DEFAULT "
|
||||||
|
+ + SubscriptionManager.INVALID_SUBSCRIPTION_ID + ", " +
|
||||||
|
+ Mms.SEEN + " INTEGER DEFAULT 0," +
|
||||||
|
+ Mms.CREATOR + " TEXT," +
|
||||||
|
+ Mms.TEXT_ONLY + " INTEGER DEFAULT 0);";
|
||||||
|
+
|
||||||
|
+ @VisibleForTesting
|
||||||
|
+ public static String CREATE_RATE_TABLE_STR =
|
||||||
|
+ "CREATE TABLE " + MmsProvider.TABLE_RATE + " (" +
|
||||||
|
+ Rate.SENT_TIME + " INTEGER);";
|
||||||
|
+
|
||||||
|
+ @VisibleForTesting
|
||||||
|
+ public static String CREATE_DRM_TABLE_STR =
|
||||||
|
+ "CREATE TABLE " + MmsProvider.TABLE_DRM + " (" +
|
||||||
|
+ BaseColumns._ID + " INTEGER PRIMARY KEY," +
|
||||||
|
+ "_data TEXT);";
|
||||||
|
+
|
||||||
|
private void createMmsTables(SQLiteDatabase db) {
|
||||||
|
// N.B.: Whenever the columns here are changed, the columns in
|
||||||
|
// {@ref MmsSmsProvider} must be changed to match.
|
||||||
|
- db.execSQL("CREATE TABLE " + MmsProvider.TABLE_PDU + " (" +
|
||||||
|
- Mms._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
|
||||||
|
- Mms.THREAD_ID + " INTEGER," +
|
||||||
|
- Mms.DATE + " INTEGER," +
|
||||||
|
- Mms.DATE_SENT + " INTEGER DEFAULT 0," +
|
||||||
|
- Mms.MESSAGE_BOX + " INTEGER," +
|
||||||
|
- Mms.READ + " INTEGER DEFAULT 0," +
|
||||||
|
- Mms.MESSAGE_ID + " TEXT," +
|
||||||
|
- Mms.SUBJECT + " TEXT," +
|
||||||
|
- Mms.SUBJECT_CHARSET + " INTEGER," +
|
||||||
|
- Mms.CONTENT_TYPE + " TEXT," +
|
||||||
|
- Mms.CONTENT_LOCATION + " TEXT," +
|
||||||
|
- Mms.EXPIRY + " INTEGER," +
|
||||||
|
- Mms.MESSAGE_CLASS + " TEXT," +
|
||||||
|
- Mms.MESSAGE_TYPE + " INTEGER," +
|
||||||
|
- Mms.MMS_VERSION + " INTEGER," +
|
||||||
|
- Mms.MESSAGE_SIZE + " INTEGER," +
|
||||||
|
- Mms.PRIORITY + " INTEGER," +
|
||||||
|
- Mms.READ_REPORT + " INTEGER," +
|
||||||
|
- Mms.REPORT_ALLOWED + " INTEGER," +
|
||||||
|
- Mms.RESPONSE_STATUS + " INTEGER," +
|
||||||
|
- Mms.STATUS + " INTEGER," +
|
||||||
|
- Mms.TRANSACTION_ID + " TEXT," +
|
||||||
|
- Mms.RETRIEVE_STATUS + " INTEGER," +
|
||||||
|
- Mms.RETRIEVE_TEXT + " TEXT," +
|
||||||
|
- Mms.RETRIEVE_TEXT_CHARSET + " INTEGER," +
|
||||||
|
- Mms.READ_STATUS + " INTEGER," +
|
||||||
|
- Mms.CONTENT_CLASS + " INTEGER," +
|
||||||
|
- Mms.RESPONSE_TEXT + " TEXT," +
|
||||||
|
- Mms.DELIVERY_TIME + " INTEGER," +
|
||||||
|
- Mms.DELIVERY_REPORT + " INTEGER," +
|
||||||
|
- Mms.LOCKED + " INTEGER DEFAULT 0," +
|
||||||
|
- Mms.SUBSCRIPTION_ID + " INTEGER DEFAULT "
|
||||||
|
- + SubscriptionManager.INVALID_SUBSCRIPTION_ID + ", " +
|
||||||
|
- Mms.SEEN + " INTEGER DEFAULT 0," +
|
||||||
|
- Mms.CREATOR + " TEXT," +
|
||||||
|
- Mms.TEXT_ONLY + " INTEGER DEFAULT 0" +
|
||||||
|
- ");");
|
||||||
|
-
|
||||||
|
- db.execSQL("CREATE TABLE " + MmsProvider.TABLE_ADDR + " (" +
|
||||||
|
- Addr._ID + " INTEGER PRIMARY KEY," +
|
||||||
|
- Addr.MSG_ID + " INTEGER," +
|
||||||
|
- Addr.CONTACT_ID + " INTEGER," +
|
||||||
|
- Addr.ADDRESS + " TEXT," +
|
||||||
|
- Addr.TYPE + " INTEGER," +
|
||||||
|
- Addr.CHARSET + " INTEGER);");
|
||||||
|
-
|
||||||
|
- db.execSQL("CREATE TABLE " + MmsProvider.TABLE_PART + " (" +
|
||||||
|
- Part._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
|
||||||
|
- Part.MSG_ID + " INTEGER," +
|
||||||
|
- Part.SEQ + " INTEGER DEFAULT 0," +
|
||||||
|
- Part.CONTENT_TYPE + " TEXT," +
|
||||||
|
- Part.NAME + " TEXT," +
|
||||||
|
- Part.CHARSET + " INTEGER," +
|
||||||
|
- Part.CONTENT_DISPOSITION + " TEXT," +
|
||||||
|
- Part.FILENAME + " TEXT," +
|
||||||
|
- Part.CONTENT_ID + " TEXT," +
|
||||||
|
- Part.CONTENT_LOCATION + " TEXT," +
|
||||||
|
- Part.CT_START + " INTEGER," +
|
||||||
|
- Part.CT_TYPE + " TEXT," +
|
||||||
|
- Part._DATA + " TEXT," +
|
||||||
|
- Part.TEXT + " TEXT);");
|
||||||
|
-
|
||||||
|
- db.execSQL("CREATE TABLE " + MmsProvider.TABLE_RATE + " (" +
|
||||||
|
- Rate.SENT_TIME + " INTEGER);");
|
||||||
|
-
|
||||||
|
- db.execSQL("CREATE TABLE " + MmsProvider.TABLE_DRM + " (" +
|
||||||
|
- BaseColumns._ID + " INTEGER PRIMARY KEY," +
|
||||||
|
- "_data TEXT);");
|
||||||
|
+ db.execSQL(CREATE_PDU_TABLE_STR);
|
||||||
|
+
|
||||||
|
+ db.execSQL(CREATE_ADDR_TABLE_STR);
|
||||||
|
+
|
||||||
|
+ db.execSQL(CREATE_PART_TABLE_STR);
|
||||||
|
+
|
||||||
|
+ db.execSQL(CREATE_RATE_TABLE_STR);
|
||||||
|
+
|
||||||
|
+ db.execSQL(CREATE_DRM_TABLE_STR);
|
||||||
|
|
||||||
|
// Restricted view of pdu table, only sent/received messages without wap pushes
|
||||||
|
db.execSQL("CREATE VIEW " + MmsProvider.VIEW_PDU_RESTRICTED + " AS " +
|
||||||
|
diff --git a/src/com/android/providers/telephony/MmsSmsProvider.java b/src/com/android/providers/telephony/MmsSmsProvider.java
|
||||||
|
index 1653cd98..ce83d679 100644
|
||||||
|
--- a/src/com/android/providers/telephony/MmsSmsProvider.java
|
||||||
|
+++ b/src/com/android/providers/telephony/MmsSmsProvider.java
|
||||||
|
@@ -23,6 +23,7 @@ import android.content.Context;
|
||||||
|
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;
|
||||||
|
@@ -30,6 +31,7 @@ import android.net.Uri;
|
||||||
|
import android.os.Binder;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.UserHandle;
|
||||||
|
+import android.os.UserManager;
|
||||||
|
import android.provider.BaseColumns;
|
||||||
|
import android.provider.Telephony;
|
||||||
|
import android.provider.Telephony.CanonicalAddressesColumns;
|
||||||
|
@@ -323,6 +325,16 @@ public class MmsSmsProvider extends ContentProvider {
|
||||||
|
@Override
|
||||||
|
public Cursor query(Uri uri, String[] projection,
|
||||||
|
String selection, String[] selectionArgs, String sortOrder) {
|
||||||
|
+ Cursor emptyCursor = new MatrixCursor((projection == null) ?
|
||||||
|
+ (new String[] {}) : projection);
|
||||||
|
+ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
|
||||||
|
+ if ((userManager != null) && (userManager.isManagedProfile(
|
||||||
|
+ Binder.getCallingUserHandle().getIdentifier()))) {
|
||||||
|
+ // If work profile is trying to query mms/sms, return empty cursor.
|
||||||
|
+ Log.e(LOG_TAG, "Managed profile is not allowed to query MMS/SMS.");
|
||||||
|
+ return emptyCursor;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
// 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
|
||||||
|
@@ -1216,6 +1228,14 @@ public class MmsSmsProvider extends ContentProvider {
|
||||||
|
@Override
|
||||||
|
public int delete(Uri uri, String selection,
|
||||||
|
String[] selectionArgs) {
|
||||||
|
+ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
|
||||||
|
+ if ((userManager != null) && (userManager.isManagedProfile(
|
||||||
|
+ Binder.getCallingUserHandle().getIdentifier()))) {
|
||||||
|
+ // If work profile is trying to delete mms/sms, return 0.
|
||||||
|
+ Log.e(LOG_TAG, "Managed profile is not allowed to delete MMS/SMS.");
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
|
||||||
|
Context context = getContext();
|
||||||
|
int affectedRows = 0;
|
||||||
|
@@ -1272,6 +1292,14 @@ public class MmsSmsProvider extends ContentProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Uri insert(Uri uri, ContentValues values) {
|
||||||
|
+ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
|
||||||
|
+ if ((userManager != null) && (userManager.isManagedProfile(
|
||||||
|
+ Binder.getCallingUserHandle().getIdentifier()))) {
|
||||||
|
+ // If work profile is trying to insert mms/sms, return null.
|
||||||
|
+ Log.e(LOG_TAG, "Managed profile is not allowed to insert MMS/SMS.");
|
||||||
|
+ return null;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (URI_MATCHER.match(uri) == URI_PENDING_MSG) {
|
||||||
|
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
|
||||||
|
long rowId = db.insert(TABLE_PENDING_MSG, null, values);
|
||||||
|
@@ -1283,6 +1311,14 @@ public class MmsSmsProvider extends ContentProvider {
|
||||||
|
@Override
|
||||||
|
public int update(Uri uri, ContentValues values,
|
||||||
|
String selection, String[] selectionArgs) {
|
||||||
|
+ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
|
||||||
|
+ if ((userManager != null) && (userManager.isManagedProfile(
|
||||||
|
+ Binder.getCallingUserHandle().getIdentifier()))) {
|
||||||
|
+ // If work profile is trying to update mms/sms, return 0.
|
||||||
|
+ Log.e(LOG_TAG, "Managed profile is not allowed to update MMS/SMS.");
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
final int callerUid = Binder.getCallingUid();
|
||||||
|
final String callerPkg = getCallingPackage();
|
||||||
|
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
|
||||||
|
diff --git a/src/com/android/providers/telephony/SmsProvider.java b/src/com/android/providers/telephony/SmsProvider.java
|
||||||
|
index 37a10448..d5f48536 100644
|
||||||
|
--- a/src/com/android/providers/telephony/SmsProvider.java
|
||||||
|
+++ b/src/com/android/providers/telephony/SmsProvider.java
|
||||||
|
@@ -32,6 +32,7 @@ import android.database.sqlite.SQLiteQueryBuilder;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Binder;
|
||||||
|
import android.os.UserHandle;
|
||||||
|
+import android.os.UserManager;
|
||||||
|
import android.provider.Contacts;
|
||||||
|
import android.provider.Telephony;
|
||||||
|
import android.provider.Telephony.MmsSms;
|
||||||
|
@@ -109,6 +110,16 @@ public class SmsProvider extends ContentProvider {
|
||||||
|
@Override
|
||||||
|
public Cursor query(Uri url, String[] projectionIn, String selection,
|
||||||
|
String[] selectionArgs, String sort) {
|
||||||
|
+ Cursor emptyCursor = new MatrixCursor((projectionIn == null) ?
|
||||||
|
+ (new String[] {}) : projectionIn);
|
||||||
|
+ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
|
||||||
|
+ if ((userManager != null) && (userManager.isManagedProfile(
|
||||||
|
+ Binder.getCallingUserHandle().getIdentifier()))) {
|
||||||
|
+ // If work profile is trying to query sms, return empty cursor.
|
||||||
|
+ Log.e(TAG, "Managed profile is not allowed to query SMS.");
|
||||||
|
+ return emptyCursor;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
// 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
|
||||||
|
@@ -453,6 +464,14 @@ public class SmsProvider extends ContentProvider {
|
||||||
|
}
|
||||||
|
|
||||||
|
private Uri insertInner(Uri url, ContentValues initialValues, int callerUid, String callerPkg) {
|
||||||
|
+ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
|
||||||
|
+ if ((userManager != null) && (userManager.isManagedProfile(
|
||||||
|
+ Binder.getCallingUserHandle().getIdentifier()))) {
|
||||||
|
+ // If work profile is trying to insert sms, return null.
|
||||||
|
+ Log.e(TAG, "Managed profile is not allowed to insert SMS.");
|
||||||
|
+ return null;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
ContentValues values;
|
||||||
|
long rowID;
|
||||||
|
int type = Sms.MESSAGE_TYPE_ALL;
|
||||||
|
@@ -646,6 +665,14 @@ public class SmsProvider extends ContentProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int delete(Uri url, String where, String[] whereArgs) {
|
||||||
|
+ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
|
||||||
|
+ if ((userManager != null) && (userManager.isManagedProfile(
|
||||||
|
+ Binder.getCallingUserHandle().getIdentifier()))) {
|
||||||
|
+ // If work profile is trying to delete sms, return 0.
|
||||||
|
+ Log.e(TAG, "Managed profile is not allowed to delete SMS.");
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
int count;
|
||||||
|
int match = sURLMatcher.match(url);
|
||||||
|
SQLiteDatabase db = getWritableDatabase(match);
|
||||||
|
@@ -748,6 +775,14 @@ public class SmsProvider extends ContentProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int update(Uri url, ContentValues values, String where, String[] whereArgs) {
|
||||||
|
+ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
|
||||||
|
+ if ((userManager != null) && (userManager.isManagedProfile(
|
||||||
|
+ Binder.getCallingUserHandle().getIdentifier()))) {
|
||||||
|
+ // If work profile is trying to update sms, return 0.
|
||||||
|
+ Log.e(TAG, "Managed profile is not allowed to update SMS.");
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
final int callerUid = Binder.getCallingUid();
|
||||||
|
final String callerPkg = getCallingPackage();
|
||||||
|
int count = 0;
|
||||||
|
diff --git a/tests/src/com/android/providers/telephony/MmsProviderTest.java b/tests/src/com/android/providers/telephony/MmsProviderTest.java
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..e1010e01
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tests/src/com/android/providers/telephony/MmsProviderTest.java
|
||||||
|
@@ -0,0 +1,173 @@
|
||||||
|
+/*
|
||||||
|
+ * Copyright (C) 2023 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 org.mockito.ArgumentMatchers.anyInt;
|
||||||
|
+import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
+import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
+import static org.mockito.Mockito.mock;
|
||||||
|
+import static org.mockito.Mockito.when;
|
||||||
|
+
|
||||||
|
+import android.app.AppOpsManager;
|
||||||
|
+import android.content.ContentValues;
|
||||||
|
+import android.content.Context;
|
||||||
|
+import android.content.pm.PackageManager;
|
||||||
|
+import android.content.pm.ProviderInfo;
|
||||||
|
+import android.database.ContentObserver;
|
||||||
|
+import android.database.Cursor;
|
||||||
|
+import android.net.Uri;
|
||||||
|
+import android.os.UserManager;
|
||||||
|
+import android.provider.Telephony;
|
||||||
|
+import android.telephony.TelephonyManager;
|
||||||
|
+import android.test.mock.MockContentResolver;
|
||||||
|
+import android.util.Log;
|
||||||
|
+
|
||||||
|
+import junit.framework.TestCase;
|
||||||
|
+
|
||||||
|
+import org.junit.Test;
|
||||||
|
+import org.mockito.Mock;
|
||||||
|
+import org.mockito.MockitoAnnotations;
|
||||||
|
+
|
||||||
|
+public class MmsProviderTest extends TestCase {
|
||||||
|
+ private static final String TAG = "MmsProviderTest";
|
||||||
|
+
|
||||||
|
+ @Mock private Context mContext;
|
||||||
|
+ private MockContentResolver mContentResolver;
|
||||||
|
+ private MmsProviderTestable mMmsProviderTestable;
|
||||||
|
+ @Mock private PackageManager mPackageManager;
|
||||||
|
+
|
||||||
|
+ private int notifyChangeCount;
|
||||||
|
+ private UserManager mUserManager;
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ protected void setUp() throws Exception {
|
||||||
|
+ super.setUp();
|
||||||
|
+ MockitoAnnotations.initMocks(this);
|
||||||
|
+ mMmsProviderTestable = new MmsProviderTestable();
|
||||||
|
+ mUserManager = mock(UserManager.class);
|
||||||
|
+
|
||||||
|
+ // setup mocks
|
||||||
|
+ when(mContext.getSystemService(eq(Context.APP_OPS_SERVICE)))
|
||||||
|
+ .thenReturn(mock(AppOpsManager.class));
|
||||||
|
+ when(mContext.getSystemService(eq(Context.TELEPHONY_SERVICE)))
|
||||||
|
+ .thenReturn(mock(TelephonyManager.class));
|
||||||
|
+ when(mContext.getSystemService(eq(Context.USER_SERVICE)))
|
||||||
|
+ .thenReturn(mUserManager);
|
||||||
|
+
|
||||||
|
+ when(mContext.checkCallingOrSelfPermission(anyString()))
|
||||||
|
+ .thenReturn(PackageManager.PERMISSION_GRANTED);
|
||||||
|
+ when(mContext.getUserId()).thenReturn(0);
|
||||||
|
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * This is used to give the MmsProviderTest a mocked context which takes a
|
||||||
|
+ * SmsProvider and attaches it to the ContentResolver with telephony authority.
|
||||||
|
+ * The mocked context also gives WRITE_APN_SETTINGS permissions
|
||||||
|
+ */
|
||||||
|
+ mContentResolver = new MockContentResolver() {
|
||||||
|
+ @Override
|
||||||
|
+ public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork,
|
||||||
|
+ int userHandle) {
|
||||||
|
+ notifyChangeCount++;
|
||||||
|
+ }
|
||||||
|
+ };
|
||||||
|
+ when(mContext.getContentResolver()).thenReturn(mContentResolver);
|
||||||
|
+
|
||||||
|
+ // Add authority="mms" to given mmsProvider
|
||||||
|
+ ProviderInfo providerInfo = new ProviderInfo();
|
||||||
|
+ providerInfo.authority = "mms";
|
||||||
|
+
|
||||||
|
+ // Add context to given mmsProvider
|
||||||
|
+ mMmsProviderTestable.attachInfoForTesting(mContext, providerInfo);
|
||||||
|
+ Log.d(TAG, "MockContextWithProvider: mmsProvider.getContext(): "
|
||||||
|
+ + mMmsProviderTestable.getContext());
|
||||||
|
+
|
||||||
|
+ // Add given MmsProvider to mResolver with authority="mms" so that
|
||||||
|
+ // mResolver can send queries to mMmsProvider
|
||||||
|
+ mContentResolver.addProvider("mms", mMmsProviderTestable);
|
||||||
|
+ Log.d(TAG, "MockContextWithProvider: Add MmsProvider to mResolver");
|
||||||
|
+ notifyChangeCount = 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ protected void tearDown() throws Exception {
|
||||||
|
+ super.tearDown();
|
||||||
|
+ mMmsProviderTestable.closeDatabase();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Test
|
||||||
|
+ public void testInsertMms() {
|
||||||
|
+ final ContentValues values = new ContentValues();
|
||||||
|
+ values.put(Telephony.Mms.READ, 1);
|
||||||
|
+ values.put(Telephony.Mms.SEEN, 1);
|
||||||
|
+ values.put(Telephony.Mms.SUBSCRIPTION_ID, 1);
|
||||||
|
+ values.put(Telephony.Mms.MESSAGE_BOX, Telephony.Mms.MESSAGE_BOX_ALL);
|
||||||
|
+ values.put(Telephony.Mms.TEXT_ONLY, 1);
|
||||||
|
+ values.put(Telephony.Mms.THREAD_ID, 1);
|
||||||
|
+
|
||||||
|
+ Uri expected = Uri.parse("content://mms/1");
|
||||||
|
+ Uri actual = mContentResolver.insert(Telephony.Mms.CONTENT_URI, values);
|
||||||
|
+
|
||||||
|
+ assertEquals(expected, actual);
|
||||||
|
+ assertEquals(1, notifyChangeCount);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Test
|
||||||
|
+ public void testInsertUsingManagedProfile() {
|
||||||
|
+ when(mUserManager.isManagedProfile(anyInt())).thenReturn(true);
|
||||||
|
+
|
||||||
|
+ try {
|
||||||
|
+ assertNull(mContentResolver.insert(Telephony.Mms.CONTENT_URI, null));
|
||||||
|
+ } catch (Exception e) {
|
||||||
|
+ Log.d(TAG, "Error inserting mms: " + e);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Test
|
||||||
|
+ public void testQueryUsingManagedProfile() {
|
||||||
|
+ when(mUserManager.isManagedProfile(anyInt())).thenReturn(true);
|
||||||
|
+
|
||||||
|
+ try (Cursor cursor = mContentResolver.query(Telephony.Mms.CONTENT_URI,
|
||||||
|
+ null, null, null, null)) {
|
||||||
|
+ assertEquals(0, cursor.getCount());
|
||||||
|
+ } catch (Exception e) {
|
||||||
|
+ Log.d(TAG, "Exception in getting count: " + e);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Test
|
||||||
|
+ public void testUpdateUsingManagedProfile() {
|
||||||
|
+ when(mUserManager.isManagedProfile(anyInt())).thenReturn(true);
|
||||||
|
+
|
||||||
|
+ try {
|
||||||
|
+ assertEquals(0, mContentResolver.update(Telephony.Mms.CONTENT_URI, null, null, null));
|
||||||
|
+ } catch (Exception e) {
|
||||||
|
+ Log.d(TAG, "Exception in updating mms: " + e);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Test
|
||||||
|
+ public void testDeleteUsingManagedProfile() {
|
||||||
|
+ when(mUserManager.isManagedProfile(anyInt())).thenReturn(true);
|
||||||
|
+
|
||||||
|
+ try {
|
||||||
|
+ assertEquals(0, mContentResolver.delete(Telephony.Mms.CONTENT_URI, null, null));
|
||||||
|
+ } catch (Exception e) {
|
||||||
|
+ Log.d(TAG, "Exception in deleting mms: " + e);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
diff --git a/tests/src/com/android/providers/telephony/MmsProviderTestable.java b/tests/src/com/android/providers/telephony/MmsProviderTestable.java
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..cea411be
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tests/src/com/android/providers/telephony/MmsProviderTestable.java
|
||||||
|
@@ -0,0 +1,77 @@
|
||||||
|
+/*
|
||||||
|
+ * Copyright (C) 2023 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.android.providers.telephony.MmsSmsDatabaseHelper.CREATE_ADDR_TABLE_STR;
|
||||||
|
+import static com.android.providers.telephony.MmsSmsDatabaseHelper.CREATE_DRM_TABLE_STR;
|
||||||
|
+import static com.android.providers.telephony.MmsSmsDatabaseHelper.CREATE_PART_TABLE_STR;
|
||||||
|
+import static com.android.providers.telephony.MmsSmsDatabaseHelper.CREATE_PDU_TABLE_STR;
|
||||||
|
+import static com.android.providers.telephony.MmsSmsDatabaseHelper.CREATE_RATE_TABLE_STR;
|
||||||
|
+
|
||||||
|
+import android.database.sqlite.SQLiteDatabase;
|
||||||
|
+import android.database.sqlite.SQLiteOpenHelper;
|
||||||
|
+import android.util.Log;
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * A subclass of MmsProvider used for testing on an in-memory database
|
||||||
|
+ */
|
||||||
|
+public class MmsProviderTestable extends MmsProvider {
|
||||||
|
+ private static final String TAG = "MmsProviderTestable";
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public boolean onCreate() {
|
||||||
|
+ Log.d(TAG, "onCreate called: mDbHelper = new InMemoryMmsProviderDbHelper()");
|
||||||
|
+ mOpenHelper = new InMemoryMmsProviderDbHelper();
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ // close mDbHelper database object
|
||||||
|
+ protected void closeDatabase() {
|
||||||
|
+ mOpenHelper.close();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * An in memory DB for MmsProviderTestable to use
|
||||||
|
+ */
|
||||||
|
+ public static class InMemoryMmsProviderDbHelper extends SQLiteOpenHelper {
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+ public InMemoryMmsProviderDbHelper() {
|
||||||
|
+ super(null, // no context is needed for in-memory db
|
||||||
|
+ null, // db file name is null for in-memory db
|
||||||
|
+ null, // CursorFactory is null by default
|
||||||
|
+ 1); // db version is no-op for tests
|
||||||
|
+ Log.d(TAG, "InMemoryMmsProviderDbHelper creating in-memory database");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public void onCreate(SQLiteDatabase db) {
|
||||||
|
+ // Set up the mms tables
|
||||||
|
+ Log.d(TAG, "InMemoryMmsProviderDbHelper onCreate creating the mms tables");
|
||||||
|
+ db.execSQL(CREATE_PDU_TABLE_STR);
|
||||||
|
+ db.execSQL(CREATE_ADDR_TABLE_STR);
|
||||||
|
+ db.execSQL(CREATE_PART_TABLE_STR);
|
||||||
|
+ db.execSQL(CREATE_RATE_TABLE_STR);
|
||||||
|
+ db.execSQL(CREATE_DRM_TABLE_STR);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||||
|
+ Log.d(TAG, "InMemorySmsProviderDbHelper onUpgrade doing nothing");
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
diff --git a/tests/src/com/android/providers/telephony/SmsProviderTest.java b/tests/src/com/android/providers/telephony/SmsProviderTest.java
|
||||||
|
index 8fba85b5..a3b88e32 100644
|
||||||
|
--- a/tests/src/com/android/providers/telephony/SmsProviderTest.java
|
||||||
|
+++ b/tests/src/com/android/providers/telephony/SmsProviderTest.java
|
||||||
|
@@ -16,6 +16,9 @@
|
||||||
|
|
||||||
|
package com.android.providers.telephony;
|
||||||
|
|
||||||
|
+import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
|
+import static org.mockito.Mockito.when;
|
||||||
|
+
|
||||||
|
import android.app.AppOpsManager;
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.content.Context;
|
||||||
|
@@ -24,6 +27,7 @@ import android.content.pm.ProviderInfo;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.database.ContentObserver;
|
||||||
|
import android.net.Uri;
|
||||||
|
+import android.os.UserManager;
|
||||||
|
import android.provider.Telephony;
|
||||||
|
import android.telephony.TelephonyManager;
|
||||||
|
import android.test.mock.MockContentResolver;
|
||||||
|
@@ -55,6 +59,7 @@ public class SmsProviderTest extends TestCase {
|
||||||
|
private MockContextWithProvider mContext;
|
||||||
|
private MockContentResolver mContentResolver;
|
||||||
|
private SmsProviderTestable mSmsProviderTestable;
|
||||||
|
+ private UserManager mUserManager;
|
||||||
|
|
||||||
|
private int notifyChangeCount;
|
||||||
|
|
||||||
|
@@ -99,6 +104,8 @@ public class SmsProviderTest extends TestCase {
|
||||||
|
return Mockito.mock(AppOpsManager.class);
|
||||||
|
case Context.TELEPHONY_SERVICE:
|
||||||
|
return Mockito.mock(TelephonyManager.class);
|
||||||
|
+ case Context.USER_SERVICE:
|
||||||
|
+ return mUserManager;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
@@ -132,6 +139,8 @@ public class SmsProviderTest extends TestCase {
|
||||||
|
mSmsProviderTestable = new SmsProviderTestable();
|
||||||
|
mContext = new MockContextWithProvider(mSmsProviderTestable);
|
||||||
|
mContentResolver = mContext.getContentResolver();
|
||||||
|
+ mUserManager = Mockito.mock(UserManager.class);
|
||||||
|
+
|
||||||
|
notifyChangeCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -170,4 +179,49 @@ public class SmsProviderTest extends TestCase {
|
||||||
|
assertEquals(Uri.parse("content://sms/attachments/1"),
|
||||||
|
mContentResolver.insert(Uri.parse("content://sms/attachments"), values));
|
||||||
|
}
|
||||||
|
-}
|
||||||
|
\ No newline at end of file
|
||||||
|
+
|
||||||
|
+ @Test
|
||||||
|
+ public void testInsertUsingManagedProfile() {
|
||||||
|
+ when(mUserManager.isManagedProfile(anyInt())).thenReturn(true);
|
||||||
|
+
|
||||||
|
+ try {
|
||||||
|
+ assertNull(mContentResolver.insert(Telephony.Sms.CONTENT_URI, null));
|
||||||
|
+ } catch (Exception e) {
|
||||||
|
+ Log.d(TAG, "Error inserting sms: " + e);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Test
|
||||||
|
+ public void testQueryUsingManagedProfile() {
|
||||||
|
+ when(mUserManager.isManagedProfile(anyInt())).thenReturn(true);
|
||||||
|
+
|
||||||
|
+ try (Cursor cursor = mContentResolver.query(Telephony.Sms.CONTENT_URI,
|
||||||
|
+ null, null, null, null)) {
|
||||||
|
+ assertEquals(0, cursor.getCount());
|
||||||
|
+ } catch (Exception e) {
|
||||||
|
+ Log.d(TAG, "Exception in getting count: " + e);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Test
|
||||||
|
+ public void testUpdateUsingManagedProfile() {
|
||||||
|
+ when(mUserManager.isManagedProfile(anyInt())).thenReturn(true);
|
||||||
|
+
|
||||||
|
+ try {
|
||||||
|
+ assertEquals(0, mContentResolver.update(Telephony.Sms.CONTENT_URI, null, null, null));
|
||||||
|
+ } catch (Exception e) {
|
||||||
|
+ Log.d(TAG, "Exception in updating sms: " + e);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Test
|
||||||
|
+ public void testDeleteUsingManagedProfile() {
|
||||||
|
+ when(mUserManager.isManagedProfile(anyInt())).thenReturn(true);
|
||||||
|
+
|
||||||
|
+ try {
|
||||||
|
+ assertEquals(0, mContentResolver.delete(Telephony.Sms.CONTENT_URI, null, null));
|
||||||
|
+ } catch (Exception e) {
|
||||||
|
+ Log.d(TAG, "Exception in deleting sms: " + e);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+}
|
@ -74,7 +74,7 @@ applyPatch "$DOS_PATCHES/android_build/0002-Enable_fwrapv.patch"; #Use -fwrapv a
|
|||||||
applyPatch "$DOS_PATCHES/android_build/0003-verity-openssl3.patch"; #Fix VB 1.0 failure due to openssl output format change
|
applyPatch "$DOS_PATCHES/android_build/0003-verity-openssl3.patch"; #Fix VB 1.0 failure due to openssl output format change
|
||||||
sed -i '57i$(my_res_package): PRIVATE_AAPT_FLAGS += --auto-add-overlay' core/aapt2.mk; #Enable auto-add-overlay for packages, this allows the vendor overlay to easily work across all branches.
|
sed -i '57i$(my_res_package): PRIVATE_AAPT_FLAGS += --auto-add-overlay' core/aapt2.mk; #Enable auto-add-overlay for packages, this allows the vendor overlay to easily work across all branches.
|
||||||
awk -i inplace '!/Email/' target/product/core.mk; #Remove Email
|
awk -i inplace '!/Email/' target/product/core.mk; #Remove Email
|
||||||
sed -i 's/2021-10-05/2023-10-05/' core/version_defaults.mk; #Bump Security String #XXX
|
sed -i 's/2021-10-05/2023-11-05/' core/version_defaults.mk; #Bump Security String #XXX
|
||||||
fi;
|
fi;
|
||||||
|
|
||||||
if enterAndClear "build/soong"; then
|
if enterAndClear "build/soong"; then
|
||||||
@ -139,6 +139,7 @@ git revert --no-edit 1419d63b4889a26d22443fd8df1f9073bf229d3d; #Add back Makefil
|
|||||||
fi;
|
fi;
|
||||||
|
|
||||||
if enterAndClear "external/webp"; then
|
if enterAndClear "external/webp"; then
|
||||||
|
applyPatch "$DOS_PATCHES_COMMON/android_external_webp/373948.patch"; #R_asb_2023-11 Update to v1.1.0-8-g50f60add
|
||||||
sed -i '85i\ \ \ \ \ \ \ \ "src/utils/filters_utils.c",' Android.bp; #Fixup
|
sed -i '85i\ \ \ \ \ \ \ \ "src/utils/filters_utils.c",' Android.bp; #Fixup
|
||||||
fi;
|
fi;
|
||||||
|
|
||||||
@ -150,6 +151,7 @@ if enterAndClear "frameworks/av"; then
|
|||||||
#if [ "$DOS_GRAPHENE_MALLOC_BROKEN" = true ]; then applyPatch "$DOS_PATCHES/android_frameworks_av/0001-HM-No_RLIMIT_AS.patch"; fi; #(GrapheneOS)
|
#if [ "$DOS_GRAPHENE_MALLOC_BROKEN" = true ]; then applyPatch "$DOS_PATCHES/android_frameworks_av/0001-HM-No_RLIMIT_AS.patch"; fi; #(GrapheneOS)
|
||||||
applyPatch "$DOS_PATCHES/android_frameworks_av/358729.patch"; #n-asb-2023-06 Fix NuMediaExtractor::readSampleData buffer Handling
|
applyPatch "$DOS_PATCHES/android_frameworks_av/358729.patch"; #n-asb-2023-06 Fix NuMediaExtractor::readSampleData buffer Handling
|
||||||
applyPatch "$DOS_PATCHES/android_frameworks_av/365962.patch"; #R_asb_2023-09 Fix Segv on unknown address error flagged by fuzzer test.
|
applyPatch "$DOS_PATCHES/android_frameworks_av/365962.patch"; #R_asb_2023-09 Fix Segv on unknown address error flagged by fuzzer test.
|
||||||
|
applyPatch "$DOS_PATCHES/android_frameworks_av/373949.patch"; #R_asb_2023-11 Fix for heap buffer overflow issue flagged by fuzzer test.
|
||||||
fi;
|
fi;
|
||||||
|
|
||||||
if enterAndClear "frameworks/base"; then
|
if enterAndClear "frameworks/base"; then
|
||||||
@ -221,6 +223,8 @@ applyPatch "$DOS_PATCHES/android_frameworks_base/368059.patch"; #R_asb_2023-10 D
|
|||||||
applyPatch "$DOS_PATCHES/android_frameworks_base/368061.patch"; #R_asb_2023-10 Fix KCM key mapping cloning
|
applyPatch "$DOS_PATCHES/android_frameworks_base/368061.patch"; #R_asb_2023-10 Fix KCM key mapping cloning
|
||||||
applyPatch "$DOS_PATCHES/android_frameworks_base/368062-backport.patch"; #R_asb_2023-10 Disallow loading icon from content URI to PipMenu
|
applyPatch "$DOS_PATCHES/android_frameworks_base/368062-backport.patch"; #R_asb_2023-10 Disallow loading icon from content URI to PipMenu
|
||||||
applyPatch "$DOS_PATCHES/android_frameworks_base/368063.patch"; #R_asb_2023-10 Fixing DatabaseUtils to detect malformed UTF-16 strings
|
applyPatch "$DOS_PATCHES/android_frameworks_base/368063.patch"; #R_asb_2023-10 Fixing DatabaseUtils to detect malformed UTF-16 strings
|
||||||
|
applyPatch "$DOS_PATCHES/android_frameworks_base/373953.patch"; #R_asb_2023-11 Use type safe API of readParcelableArray
|
||||||
|
applyPatch "$DOS_PATCHES/android_frameworks_base/373955.patch"; #R_asb_2023-11 [SettingsProvider] verify ringtone URI before setting
|
||||||
applyPatch "$DOS_PATCHES_COMMON/android_frameworks_base/0001-Browser_No_Location.patch"; #Don't grant location permission to system browsers (GrapheneOS)
|
applyPatch "$DOS_PATCHES_COMMON/android_frameworks_base/0001-Browser_No_Location.patch"; #Don't grant location permission to system browsers (GrapheneOS)
|
||||||
applyPatch "$DOS_PATCHES_COMMON/android_frameworks_base/0003-SUPL_No_IMSI.patch"; #Don't send IMSI to SUPL (MSe1969)
|
applyPatch "$DOS_PATCHES_COMMON/android_frameworks_base/0003-SUPL_No_IMSI.patch"; #Don't send IMSI to SUPL (MSe1969)
|
||||||
applyPatch "$DOS_PATCHES_COMMON/android_frameworks_base/0004-Fingerprint_Lockout.patch"; #Enable fingerprint lockout after five failed attempts (GrapheneOS)
|
applyPatch "$DOS_PATCHES_COMMON/android_frameworks_base/0004-Fingerprint_Lockout.patch"; #Enable fingerprint lockout after five failed attempts (GrapheneOS)
|
||||||
@ -420,6 +424,7 @@ fi;
|
|||||||
if enterAndClear "packages/providers/TelephonyProvider"; then
|
if enterAndClear "packages/providers/TelephonyProvider"; then
|
||||||
applyPatch "$DOS_PATCHES/android_packages_providers_TelephonyProvider/344182.patch"; #P_asb_2022-11 Check dir path before updating permissions.
|
applyPatch "$DOS_PATCHES/android_packages_providers_TelephonyProvider/344182.patch"; #P_asb_2022-11 Check dir path before updating permissions.
|
||||||
applyPatch "$DOS_PATCHES/android_packages_providers_TelephonyProvider/364040-backport.patch"; #R_asb_2023-08 Update file permissions using canonical path
|
applyPatch "$DOS_PATCHES/android_packages_providers_TelephonyProvider/364040-backport.patch"; #R_asb_2023-08 Update file permissions using canonical path
|
||||||
|
applyPatch "$DOS_PATCHES/android_packages_providers_TelephonyProvider/373957-backport.patch"; #R_asb_2023-11 Block access to sms/mms db from work profile.
|
||||||
fi;
|
fi;
|
||||||
|
|
||||||
if enterAndClear "packages/services/Telecomm"; then
|
if enterAndClear "packages/services/Telecomm"; then
|
||||||
|
Loading…
Reference in New Issue
Block a user