From c4ce65c11ec824bc8dd5b799e8e2d721a48835b3 Mon Sep 17 00:00:00 2001 From: Santiago Seifert Date: Mon, 20 Sep 2021 17:04:48 +0100 Subject: [PATCH 1/7] Handle MediaMetadataRetriever.release IOException MediaMetadataRetriever.release now declares a thrown IOException. Bug: 200173116 Test: Should be a non-functional change (only relevant when using MediaDataSource). Change-Id: Ia3f5f01ee79feb35a10ec8bbbef6db88b32f2161 --- .../android/messaging/util/MediaMetadataRetrieverWrapper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/android/messaging/util/MediaMetadataRetrieverWrapper.java b/src/com/android/messaging/util/MediaMetadataRetrieverWrapper.java index b1078d1..1a93e9d 100644 --- a/src/com/android/messaging/util/MediaMetadataRetrieverWrapper.java +++ b/src/com/android/messaging/util/MediaMetadataRetrieverWrapper.java @@ -74,7 +74,7 @@ public class MediaMetadataRetrieverWrapper { public void release() { try { mRetriever.release(); - } catch (RuntimeException e) { + } catch (RuntimeException | IOException e) { LogUtil.e(LogUtil.BUGLE_TAG, "MediaMetadataRetriever.release failed", e); } } From 9607c95e7164e7856c45fd9d07eea9b09f9db681 Mon Sep 17 00:00:00 2001 From: Jake Klinker Date: Wed, 6 Oct 2021 21:08:32 +0000 Subject: [PATCH 2/7] Convert URI scheme to lower case before checking if it is a file. This fixes an edge case where a "File://" style URI could be passed in but not pass this check, even though the underlying framework recognizes this as a legitimate file. Bug: 197328178 Test: See repro steps on http://b/197328178, was no longer able to repro. Change-Id: Id837744a79d1aca91b41d24207dc9b98f2b5b5e9 --- src/com/android/messaging/util/UriUtil.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/com/android/messaging/util/UriUtil.java b/src/com/android/messaging/util/UriUtil.java index d336167..1d6a1be 100644 --- a/src/com/android/messaging/util/UriUtil.java +++ b/src/com/android/messaging/util/UriUtil.java @@ -94,8 +94,12 @@ public class UriUtil { return TextUtils.equals(scheme, ContentResolver.SCHEME_ANDROID_RESOURCE); } + /** Returns whether the given Uri is a file. */ public static boolean isFileUri(final Uri uri) { - return uri != null && TextUtils.equals(uri.getScheme(), ContentResolver.SCHEME_FILE); + return uri != null && + uri.getScheme() != null && + TextUtils.equals(uri.getScheme().toLowerCase(), + ContentResolver.SCHEME_FILE); } /** From f64cd7e766d6505f9ca79ba80198f64a0a57f733 Mon Sep 17 00:00:00 2001 From: Steve Elliott Date: Fri, 3 Dec 2021 16:32:57 -0500 Subject: [PATCH 3/7] add post_notification permission to manifest so the package can send notifications on T+ Bug: 194833441 Change-Id: I760b7fce2fe23a4a2c9db3b21b4cd0e6c2c769d0 --- AndroidManifest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index b25ff16..fffcdab 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -47,6 +47,7 @@ + From 0b258f030a589c83b8499d2f994c268bee92abba Mon Sep 17 00:00:00 2001 From: Jake Klinker Date: Tue, 11 Jan 2022 00:38:23 +0000 Subject: [PATCH 4/7] Fix isFileUri to recognize URIs with spaces. The underlying framework recognizes " file://..." as a valid URI and fetches the file, allowing for a possible exploit (see b/209965112). This trims the URI so that we can properly recognize it as a file from within our code. Bug: 209965112 Change-Id: I8d9d9100e9a8c3bd64d19015d2177a14ec2306f3 Test: See repro steps on http://b/209965112, was no longer able to repro. --- src/com/android/messaging/util/UriUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/android/messaging/util/UriUtil.java b/src/com/android/messaging/util/UriUtil.java index 1d6a1be..6e39749 100644 --- a/src/com/android/messaging/util/UriUtil.java +++ b/src/com/android/messaging/util/UriUtil.java @@ -98,7 +98,7 @@ public class UriUtil { public static boolean isFileUri(final Uri uri) { return uri != null && uri.getScheme() != null && - TextUtils.equals(uri.getScheme().toLowerCase(), + TextUtils.equals(uri.getScheme().trim().toLowerCase(), ContentResolver.SCHEME_FILE); } From ebc64c5bae620cb67808935b0fb61cf2cfce4a9c Mon Sep 17 00:00:00 2001 From: Jake Klinker Date: Mon, 31 Jan 2022 20:21:06 +0000 Subject: [PATCH 5/7] Use UriUtil when checking if a URI is a file. UriUtil.isFileUri contains several additional fixes, so this ensure that existing instances where we check for the file scheme use this method as well. This covers all existing instances in the app of SCHEME_FILE. Change-Id: I1f3131b33823eae3e620aa9608be8e72b2e84aa2 Bug: 215212561 --- src/com/android/messaging/mmslib/pdu/PduPersister.java | 4 ++-- src/com/android/messaging/util/FileUtil.java | 6 +----- src/com/android/messaging/util/ImageUtils.java | 2 +- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/com/android/messaging/mmslib/pdu/PduPersister.java b/src/com/android/messaging/mmslib/pdu/PduPersister.java index 6615d30..436867a 100644 --- a/src/com/android/messaging/mmslib/pdu/PduPersister.java +++ b/src/com/android/messaging/mmslib/pdu/PduPersister.java @@ -52,6 +52,7 @@ import com.android.messaging.util.Assert; import com.android.messaging.util.ContentType; import com.android.messaging.util.LogUtil; import com.android.messaging.util.OsUtil; +import com.android.messaging.util.UriUtil; import java.io.ByteArrayOutputStream; import java.io.File; @@ -1018,8 +1019,7 @@ public class PduPersister { String path = null; if (null != uri) { final String scheme = uri.getScheme(); - if (null == scheme || scheme.equals("") || - scheme.equals(ContentResolver.SCHEME_FILE)) { + if (null == scheme || scheme.equals("") || UriUtil.isFileUri(uri)) { path = uri.getPath(); } else if (scheme.equals("http")) { diff --git a/src/com/android/messaging/util/FileUtil.java b/src/com/android/messaging/util/FileUtil.java index 7d59aa7..71fbb4b 100644 --- a/src/com/android/messaging/util/FileUtil.java +++ b/src/com/android/messaging/util/FileUtil.java @@ -117,15 +117,11 @@ public class FileUtil { } } - private static boolean isFileUri(final Uri uri) { - return TextUtils.equals(uri.getScheme(), ContentResolver.SCHEME_FILE); - } - // Checks if the file is in /data, and don't allow any app to send personal information. // We're told it's possible to create world readable hardlinks to other apps private data // so we ban all /data file uris. public static boolean isInPrivateDir(Uri uri) { - if (!isFileUri(uri)) { + if (!UriUtil.isFileUri(uri)) { return false; } final File file = new File(uri.getPath()); diff --git a/src/com/android/messaging/util/ImageUtils.java b/src/com/android/messaging/util/ImageUtils.java index a228417..e541d69 100644 --- a/src/com/android/messaging/util/ImageUtils.java +++ b/src/com/android/messaging/util/ImageUtils.java @@ -480,7 +480,7 @@ public class ImageUtils { if (MediaScratchFileProvider.isMediaScratchSpaceUri(mUri)) { inputFilePath = MediaScratchFileProvider.getFileFromUri(mUri).getAbsolutePath(); } else { - if (!TextUtils.equals(mUri.getScheme(), ContentResolver.SCHEME_FILE)) { + if (!UriUtil.isFileUri(mUri)) { Assert.fail("Expected a GIF file uri, but actual uri = " + mUri.toString()); } inputFilePath = mUri.getPath(); From f62c3cd35a7888ac13eb8c8d0cc7a70364eadfa8 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Wed, 23 Mar 2022 04:18:42 +0000 Subject: [PATCH 6/7] Updating the DATA_ROAMING flag acceess from Settings to TelephonyManager API. Bug: 172467621 Test: Build Change-Id: Ide0db6ecacaabc29b5c4c53a2868d4a2ae27c646 --- src/com/android/messaging/util/PhoneUtils.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/com/android/messaging/util/PhoneUtils.java b/src/com/android/messaging/util/PhoneUtils.java index 671c65e..08889b8 100644 --- a/src/com/android/messaging/util/PhoneUtils.java +++ b/src/com/android/messaging/util/PhoneUtils.java @@ -26,7 +26,6 @@ import android.database.Cursor; import android.net.ConnectivityManager; import android.provider.Settings; import android.provider.Telephony; -import androidx.collection.ArrayMap; import android.telephony.PhoneNumberUtils; import android.telephony.SmsManager; import android.telephony.SubscriptionInfo; @@ -34,14 +33,18 @@ import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.text.TextUtils; +import androidx.collection.ArrayMap; +import androidx.core.os.BuildCompat; + import com.android.messaging.Factory; import com.android.messaging.R; import com.android.messaging.datamodel.data.ParticipantData; import com.android.messaging.sms.MmsSmsUtils; + import com.google.i18n.phonenumbers.NumberParseException; -import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber; import com.google.i18n.phonenumbers.PhoneNumberUtil; import com.google.i18n.phonenumbers.PhoneNumberUtil.PhoneNumberFormat; +import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber; import java.lang.reflect.Method; import java.util.ArrayList; @@ -369,6 +372,9 @@ public abstract class PhoneUtils { @Override @SuppressWarnings("deprecation") public boolean isDataRoamingEnabled() { + if (BuildCompat.isAtLeastT()) { + return mTelephonyManager.isDataRoamingEnabled(); + } boolean dataRoamingEnabled = false; final ContentResolver cr = mContext.getContentResolver(); if (OsUtil.isAtLeastJB_MR1()) { From c8e4ab2b22cf6551c6c464df7f261ed4d3b659a6 Mon Sep 17 00:00:00 2001 From: Jake Klinker Date: Thu, 21 Apr 2022 16:46:18 +0000 Subject: [PATCH 7/7] Fix url:file:// style URIs from not being detected in UriUtil. Change-Id: I81c01202306d856f6f8f8b74a5a28d7c1011fcec Tested: Was no longer able to repro b/222091734. Bug: 222091734 (cherry picked from commit 2283165c23b9162e99b817400889fe541799626f) --- src/com/android/messaging/util/UriUtil.java | 36 ++++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/src/com/android/messaging/util/UriUtil.java b/src/com/android/messaging/util/UriUtil.java index 6e39749..f92155f 100644 --- a/src/com/android/messaging/util/UriUtil.java +++ b/src/com/android/messaging/util/UriUtil.java @@ -49,6 +49,8 @@ public class UriUtil { private static final String SCHEME_MMSTO = "smsto"; public static final HashSet SMS_MMS_SCHEMES = new HashSet( Arrays.asList(SCHEME_SMS, SCHEME_MMS, SCHEME_SMSTO, SCHEME_MMSTO)); + private static final String SCHEME_HTTP = "http"; + private static final String SCHEME_HTTPS = "https"; public static final String SCHEME_BUGLE = "bugle"; public static final HashSet SUPPORTED_SCHEME = new HashSet( @@ -98,8 +100,7 @@ public class UriUtil { public static boolean isFileUri(final Uri uri) { return uri != null && uri.getScheme() != null && - TextUtils.equals(uri.getScheme().trim().toLowerCase(), - ContentResolver.SCHEME_FILE); + uri.getScheme().trim().toLowerCase().contains(ContentResolver.SCHEME_FILE); } /** @@ -216,9 +217,10 @@ public class UriUtil { inputStream = context.getContentResolver().openInputStream(sourceUri); } else { // The content is remote. Download it. - final URL url = new URL(sourceUri.toString()); - final URLConnection ucon = url.openConnection(); - inputStream = new BufferedInputStream(ucon.getInputStream()); + inputStream = getInputStreamFromRemoteUri(sourceUri); + if (inputStream == null) { + return null; + } } return persistContentToScratchSpace(inputStream); } catch (final Exception ex) { @@ -235,6 +237,23 @@ public class UriUtil { } } + @DoesNotRunOnMainThread + private static InputStream getInputStreamFromRemoteUri(final Uri sourceUri) + throws IOException { + if (isRemoteUri(sourceUri)) { + final URL url = new URL(sourceUri.toString()); + final URLConnection ucon = url.openConnection(); + return new BufferedInputStream(ucon.getInputStream()); + } else { + return null; + } + } + + private static boolean isRemoteUri(final Uri sourceUri) { + return sourceUri.getScheme().equals(SCHEME_HTTP) + || sourceUri.getScheme().equals(SCHEME_HTTPS); + } + /** * Persist a piece of content from the given input stream, byte by byte to the specified * directory. @@ -273,9 +292,10 @@ public class UriUtil { inputStream = context.getContentResolver().openInputStream(sourceUri); } else { // The content is remote. Download it. - final URL url = new URL(sourceUri.toString()); - final URLConnection ucon = url.openConnection(); - inputStream = new BufferedInputStream(ucon.getInputStream()); + inputStream = getInputStreamFromRemoteUri(sourceUri); + if (inputStream == null) { + return null; + } } return persistContent(inputStream, outputDir, contentType); } catch (final Exception ex) {