16.0: September 2024 ASB work

Signed-off-by: Tavi <tavi@divested.dev>
This commit is contained in:
Tavi 2024-09-15 15:44:43 -04:00
parent 40f1367bdc
commit f2eed12bab
No known key found for this signature in database
GPG Key ID: E599F62ECBAEAF2E
12 changed files with 945 additions and 15 deletions

View File

@ -67,7 +67,7 @@ external/capstone 6788a4139092f179005f7cdbf181ba24b60b6113
external/cblas ddf5f49cb53866fbc503a6349bf44bac24a6963d
external/chromium-libpac dff5ddb8d28f6ac9a86eb28763b4313f6f72eec5
external/chromium-trace b2cf025c7d5cebd43084f38c6c7ff9cc17da428a
external/chromium-webview b270aa98312408d5893ee72fcd62b4d89937ceb2
external/chromium-webview 8400ae9b819741cd4d436cce372496426ec85fc9
external/clang f9d2af42fc6d74c28893af371e4647158eaba66c
external/cmockery 9199c7bfafefea32d1884182fa655b6e4578c1c4
external/cn-cbor 7fe9f01990a97be4df5e46d2decd894c06678072

View File

@ -9,10 +9,10 @@ Reported by TaiYou
1 file changed, 6 insertions(+)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index 074c841..f4e3d2a 100644
index 90089ab7..3dc9673b 100644
--- a/lib/xmlparse.c
+++ b/lib/xmlparse.c
@@ -1969,6 +1969,12 @@ XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
@@ -1965,6 +1965,12 @@ XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
if (parser == NULL)
return XML_STATUS_ERROR;

View File

@ -9,10 +9,10 @@ Reported by TaiYou
1 file changed, 10 insertions(+)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index f4e3d2a..a6d92f4 100644
index 3dc9673b..158cb4ea 100644
--- a/lib/xmlparse.c
+++ b/lib/xmlparse.c
@@ -6639,6 +6639,16 @@ dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, const XML_Memory_H
@@ -6616,6 +6616,16 @@ dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, const XML_Memory_H
if (!newE)
return 0;
if (oldE->nDefaultAtts) {

View File

@ -9,10 +9,10 @@ Reported by TaiYou
1 file changed, 9 insertions(+)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index a6d92f4..2f48cf1 100644
index 158cb4ea..59b35841 100644
--- a/lib/xmlparse.c
+++ b/lib/xmlparse.c
@@ -7221,6 +7221,15 @@ nextScaffoldPart(XML_Parser parser)
@@ -7199,6 +7199,15 @@ nextScaffoldPart(XML_Parser parser)
int next;
if (!dtd->scaffIndex) {

View File

@ -1,4 +1,4 @@
From 33050b14552fd7d0767bdc56fc9448323443735e Mon Sep 17 00:00:00 2001
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sebastian Pipping <sebastian@pipping.org>
Date: Thu, 22 Sep 2022 16:51:17 +0200
Subject: [PATCH] lib: Stop leaking opening tag bindings after closing tag
@ -13,10 +13,10 @@ Change-Id: Ia6e29060abc733548bca1910735466c415cbd58c
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index 2f48cf1..a891f5a 100644
index 59b35841..008b92e9 100644
--- a/lib/xmlparse.c
+++ b/lib/xmlparse.c
@@ -2962,9 +2962,6 @@ doContent(XML_Parser parser,
@@ -2939,9 +2939,6 @@ doContent(XML_Parser parser,
int len;
const char *rawName;
TAG *tag = parser->m_tagStack;
@ -26,7 +26,7 @@ index 2f48cf1..a891f5a 100644
rawName = s + enc->minBytesPerChar*2;
len = XmlNameLength(enc, rawName);
if (len != tag->rawNameLength
@@ -2972,6 +2969,9 @@ doContent(XML_Parser parser,
@@ -2949,6 +2946,9 @@ doContent(XML_Parser parser,
*eventPP = rawName;
return XML_ERROR_TAG_MISMATCH;
}

View File

@ -0,0 +1,48 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alexander Grund <flamefire89@gmail.com>
Date: Tue, 27 Aug 2024 16:53:27 +0200
Subject: [PATCH] Fix flag check in JAudioTrack.cpp
Checking for a bitwise flag needs to use `&` not `|` as the latter will
yield a non-zero result in all (relevant) cases.
Change-Id: Ifd2e98e7bb394c35a8a2f4ebde512046823da043
---
media/libmediaplayer2/JAudioTrack.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/media/libmediaplayer2/JAudioTrack.cpp b/media/libmediaplayer2/JAudioTrack.cpp
index ac0cc5775e..961d7e526e 100644
--- a/media/libmediaplayer2/JAudioTrack.cpp
+++ b/media/libmediaplayer2/JAudioTrack.cpp
@@ -615,26 +615,26 @@ jobject JAudioTrack::createVolumeShaperOperationObj(
jBuilderObj = env->CallObjectMethod(jBuilderCls, jReplace, operation->getReplaceId(), join);
}
- if (flags | media::VolumeShaper::Operation::FLAG_REVERSE) {
+ if (flags & media::VolumeShaper::Operation::FLAG_REVERSE) {
jmethodID jReverse = env->GetMethodID(jBuilderCls, "reverse",
"()Landroid/media/VolumeShaper$Operation$Builder;");
jBuilderObj = env->CallObjectMethod(jBuilderCls, jReverse);
}
// TODO: VolumeShaper Javadoc says "Do not call terminate() directly". Can we call this?
- if (flags | media::VolumeShaper::Operation::FLAG_TERMINATE) {
+ if (flags & media::VolumeShaper::Operation::FLAG_TERMINATE) {
jmethodID jTerminate = env->GetMethodID(jBuilderCls, "terminate",
"()Landroid/media/VolumeShaper$Operation$Builder;");
jBuilderObj = env->CallObjectMethod(jBuilderCls, jTerminate);
}
- if (flags | media::VolumeShaper::Operation::FLAG_DELAY) {
+ if (flags & media::VolumeShaper::Operation::FLAG_DELAY) {
jmethodID jDefer = env->GetMethodID(jBuilderCls, "defer",
"()Landroid/media/VolumeShaper$Operation$Builder;");
jBuilderObj = env->CallObjectMethod(jBuilderCls, jDefer);
}
- if (flags | media::VolumeShaper::Operation::FLAG_CREATE_IF_NECESSARY) {
+ if (flags & media::VolumeShaper::Operation::FLAG_CREATE_IF_NECESSARY) {
jmethodID jCreateIfNeeded = env->GetMethodID(jBuilderCls, "createIfNeeded",
"()Landroid/media/VolumeShaper$Operation$Builder;");
jBuilderObj = env->CallObjectMethod(jBuilderCls, jCreateIfNeeded);

View File

@ -0,0 +1,66 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Kiran Ramachandra <kiranmr@google.com>
Date: Wed, 5 Jun 2024 21:03:33 +0000
Subject: [PATCH] DO NOT MERGE Ignore - Sanitized uri scheme by removing scheme
delimiter
Initially considered removing unsupported characters as per IANA guidelines, but this could break applications that use custom schemes with asterisks. Instead, opted to remove only the "://" to minimize disruption
Bug: 261721900
Test: atest FrameworksCoreTests:android.net.UriTest
No-Typo-Check: The unit test is specifically written to test few cases, string "http://https://" is not a typo
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:1fd0421801c391dd619cafeeea8d379a9029074a)
Merged-In: I88b1550a5d8b3dc0f6286e28899884025d059645
Change-Id: I88b1550a5d8b3dc0f6286e28899884025d059645
---
core/java/android/net/Uri.java | 6 +++++-
core/tests/coretests/src/android/net/UriTest.java | 11 +++++++++++
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java
index af1c0e8e9178..d0fcc4240fd9 100644
--- a/core/java/android/net/Uri.java
+++ b/core/java/android/net/Uri.java
@@ -1365,7 +1365,11 @@ public abstract class Uri implements Parcelable, Comparable<Uri> {
* @param scheme name or {@code null} if this is a relative Uri
*/
public Builder scheme(String scheme) {
- this.scheme = scheme;
+ if (scheme != null) {
+ this.scheme = scheme.replace("://", "");
+ } else {
+ this.scheme = null;
+ }
return this;
}
diff --git a/core/tests/coretests/src/android/net/UriTest.java b/core/tests/coretests/src/android/net/UriTest.java
index ea0347d67ad7..6c9fdd5a83a7 100644
--- a/core/tests/coretests/src/android/net/UriTest.java
+++ b/core/tests/coretests/src/android/net/UriTest.java
@@ -18,6 +18,7 @@ package android.net;
import android.content.ContentUris;
import android.os.Parcel;
+import android.platform.test.annotations.AsbSecurityTest;
import android.test.suitebuilder.annotation.SmallTest;
import junit.framework.TestCase;
@@ -83,6 +84,16 @@ public class UriTest extends TestCase {
assertNull(u.getHost());
}
+ @AsbSecurityTest(cveBugId = 261721900)
+ @SmallTest
+ public void testSchemeSanitization() {
+ Uri uri = new Uri.Builder()
+ .scheme("http://https://evil.com:/te:st/")
+ .authority("google.com").path("one/way").build();
+ assertEquals("httphttpsevil.com:/te:st/", uri.getScheme());
+ assertEquals("httphttpsevil.com:/te:st/://google.com/one/way", uri.toString());
+ }
+
@SmallTest
public void testStringUri() {
assertEquals("bob lee",

View File

@ -0,0 +1,28 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Chaohui Wang <chaohuiw@google.com>
Date: Thu, 2 Nov 2023 11:43:00 +0800
Subject: [PATCH] Limit wifi item edit content's max length to 500
Bug: 293199910
Test: manual - on "Add network"
(cherry picked from commit 855053ca4124f2d515b21c469096f8c18bd4829d)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:092668676af741719d50ac0f121a8f8461aa21ad)
Merged-In: I303b8c6e0f3c3a1174a047ba98f302042e5db9ae
Change-Id: I303b8c6e0f3c3a1174a047ba98f302042e5db9ae
---
res/values/styles.xml | 1 +
1 file changed, 1 insertion(+)
diff --git a/res/values/styles.xml b/res/values/styles.xml
index f82d0e5e854..b13bc4fb32b 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -221,6 +221,7 @@
<item name="android:textSize">18sp</item>
<item name="android:textAlignment">viewStart</item>
<item name="android:minHeight">@dimen/min_tap_target_size</item>
+ <item name="android:maxLength">500</item>
</style>
<style name="wifi_section">

View File

@ -1,3 +1,26 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jason Chiu <chiujason@google.com>
Date: Wed, 31 Jan 2024 16:29:01 +0800
Subject: [PATCH] Replace getCallingActivity() with getLaunchedFromPackage()
getLaunchedFromPackage() reports who launched this Activity or built
PendingIntent used to launch it, whereas getCallingActivity() reports
who will get result of Activity.
Bug: 316891059
Test: robotest, manual
(cherry picked from commit ddc11bc03ab48e885f652b89df5f92ff283bcd4a)
(cherry picked from commit 8bdbb580da847d82f16fb57883a01a5e65ffa696)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:c7a8127d3bb6010617e507c03f7207dd50082953)
Merged-In: If97018c2741caef622f0596bbfeaa42ef1788b78
Change-Id: If97018c2741caef622f0596bbfeaa42ef1788b78
---
.../search/SearchFeatureProvider.java | 2 +-
.../search/SearchFeatureProviderImpl.java | 20 +++++++++----------
.../search/SearchResultTrampoline.java | 2 +-
.../search/SearchFeatureProviderImplTest.java | 15 +++++++-------
4 files changed, 19 insertions(+), 20 deletions(-)
diff --git a/src/com/android/settings/search/SearchFeatureProvider.java b/src/com/android/settings/search/SearchFeatureProvider.java
index cbe49f8c799..9bfd5460efa 100644
--- a/src/com/android/settings/search/SearchFeatureProvider.java
@ -12,7 +35,7 @@ index cbe49f8c799..9bfd5460efa 100644
/**
diff --git a/src/com/android/settings/search/SearchFeatureProviderImpl.java b/src/com/android/settings/search/SearchFeatureProviderImpl.java
index 78c47edf046..262f220f8ab 100644
index 78c47edf046..7c88785b337 100644
--- a/src/com/android/settings/search/SearchFeatureProviderImpl.java
+++ b/src/com/android/settings/search/SearchFeatureProviderImpl.java
@@ -17,10 +17,11 @@

View File

@ -0,0 +1,112 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Chris Antol <cantol@google.com>
Date: Tue, 4 Jun 2024 17:00:46 +0000
Subject: [PATCH] Ignore fragment attr from ext authenticator resource
Bug: 341886134
Test: Unit Test
Test: Manual - see ticket for steps
Flag: EXEMPT <security>
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:2cb9b10ed97b1b9b29661115789605a762f3c2ef)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:7e0b376b11318e1e79b31bac6aafc0c923868bc4)
Merged-In: Id91c2b3b6d16ba3702ee2cd6723365a4db52863b
Change-Id: Id91c2b3b6d16ba3702ee2cd6723365a4db52863b
---
.../accounts/AccountTypePreferenceLoader.java | 56 +++++++++++++++++++
1 file changed, 56 insertions(+)
diff --git a/src/com/android/settings/accounts/AccountTypePreferenceLoader.java b/src/com/android/settings/accounts/AccountTypePreferenceLoader.java
index 3914fac39b4..ce3d61d4dfa 100644
--- a/src/com/android/settings/accounts/AccountTypePreferenceLoader.java
+++ b/src/com/android/settings/accounts/AccountTypePreferenceLoader.java
@@ -37,6 +37,11 @@ import android.support.v7.preference.PreferenceScreen;
import android.text.TextUtils;
import android.util.Log;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.annotation.VisibleForTesting;
+import android.util.ArraySet;
+
import com.android.settings.R;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.location.LocationSettings;
@@ -44,6 +49,8 @@ import com.android.settings.utils.LocalClassLoaderContextThemeWrapper;
import com.android.settingslib.accounts.AuthenticatorHelper;
import com.android.settingslib.core.instrumentation.Instrumentable;
+import java.util.Set;
+
/**
* Class to load the preference screen to be added to the settings page for the specific account
* type as specified in the account-authenticator.
@@ -82,6 +89,7 @@ public class AccountTypePreferenceLoader {
try {
desc = mAuthenticatorHelper.getAccountTypeDescription(accountType);
if (desc != null && desc.accountPreferencesId != 0) {
+ Set<String> fragmentAllowList = generateFragmentAllowlist(parent);
// Load the context of the target package, then apply the
// base Settings theme (no references to local resources)
// and create a context theme wrapper so that we get the
@@ -97,6 +105,12 @@ public class AccountTypePreferenceLoader {
themedCtx.getTheme().setTo(baseTheme);
prefs = mFragment.getPreferenceManager().inflateFromResource(themedCtx,
desc.accountPreferencesId, parent);
+ // Ignore Fragments provided dynamically, as these are coming from external
+ // applications which must not have access to internal Settings' fragments.
+ // These preferences are rendered into Settings, so they also won't have access
+ // to their own Fragments, meaning there is no acceptable usage of
+ // android:fragment here.
+ filterBlockedFragments(prefs, fragmentAllowList);
}
} catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, "Couldn't load preferences.xml file from " + desc.packageName);
@@ -181,6 +195,48 @@ public class AccountTypePreferenceLoader {
}
}
+ // Build allowlist from existing Fragments in PreferenceGroup
+ @VisibleForTesting
+ Set<String> generateFragmentAllowlist(@Nullable PreferenceGroup prefs) {
+ Set<String> fragmentAllowList = new ArraySet<>();
+ if (prefs == null) {
+ return fragmentAllowList;
+ }
+
+ for (int i = 0; i < prefs.getPreferenceCount(); i++) {
+ Preference pref = prefs.getPreference(i);
+ if (pref instanceof PreferenceGroup) {
+ fragmentAllowList.addAll(generateFragmentAllowlist((PreferenceGroup) pref));
+ }
+
+ String fragmentName = pref.getFragment();
+ if (!TextUtils.isEmpty(fragmentName)) {
+ fragmentAllowList.add(fragmentName);
+ }
+ }
+ return fragmentAllowList;
+ }
+
+ // Block clicks on any Preference with android:fragment that is not contained in the allowlist
+ @VisibleForTesting
+ void filterBlockedFragments(@Nullable PreferenceGroup prefs,
+ @NonNull Set<String> allowedFragments) {
+ if (prefs == null) {
+ return;
+ }
+ for (int i = 0; i < prefs.getPreferenceCount(); i++) {
+ Preference pref = prefs.getPreference(i);
+ if (pref instanceof PreferenceGroup) {
+ filterBlockedFragments((PreferenceGroup) pref, allowedFragments);
+ }
+
+ String fragmentName = pref.getFragment();
+ if (fragmentName != null && !allowedFragments.contains(fragmentName)) {
+ pref.setOnPreferenceClickListener(preference -> true);
+ }
+ }
+ }
+
/**
* Determines if the supplied Intent is safe. A safe intent is one that is
* will launch a exported=true activity or owned by the same uid as the

View File

@ -0,0 +1,648 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Grant Menke <grantmenke@google.com>
Date: Thu, 25 Apr 2024 10:43:43 -0700
Subject: [PATCH] DO NOT MERGE Unbind CS if connection is not created within 15
seconds.
This CL adds a check to ensure that connection creation occurs within 15 seconds after binding to that ConnectionService. If the connection/conference is not created in that timespan, this CL adds logic to manually unbind the ConnectionService at that point in time. This prevents malicious apps from keeping a declared permission in forever even in the background.
Bug: 293458004
Test: manually using the provided apk + atest CallsManagerTest
Flag: EXEMPT Security High/Critical Severity CVE
(cherry picked from commit 7aa55ffca65d6166145fd9660e0f7340c07053bf)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:286781dfcb78d8b5c1a77f2390f5251f01943add)
Merged-In: I30caed1481dff5af2223a8ff589846597cee8229
Change-Id: I30caed1481dff5af2223a8ff589846597cee8229
---
src/com/android/server/telecom/Call.java | 25 ++
.../telecom/ConnectionServiceWrapper.java | 49 ++-
src/com/android/server/telecom/LogUtils.java | 1 +
.../server/telecom/tests/BasicCallTests.java | 2 +
.../telecom/tests/CallsManagerTest.java | 60 ++++
.../tests/ComponentContextFixture.java | 14 +
.../tests/TestScheduledExecutorService.java | 283 ++++++++++++++++++
7 files changed, 432 insertions(+), 2 deletions(-)
create mode 100644 tests/src/com/android/server/telecom/tests/TestScheduledExecutorService.java
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index bc20d1caf..f4ec11187 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -306,6 +306,17 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
/** The state of the call. */
private int mState;
+ /**
+ * Determines whether the {@link ConnectionService} has responded to the initial request to
+ * create the connection.
+ *
+ * {@code false} indicates the {@link Call} has been added to Telecom, but the
+ * {@link Connection} has not yet been returned by the associated {@link ConnectionService}.
+ * {@code true} indicates the {@link Call} has an associated {@link Connection} reported by the
+ * {@link ConnectionService}.
+ */
+ private boolean mIsCreateConnectionComplete = false;
+
/** The handle with which to establish this call. */
private Uri mHandle;
@@ -797,6 +808,19 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
return mConnectionService;
}
+ /**
+ * @return {@code true} if the connection has been created by the underlying
+ * {@link ConnectionService}, {@code false} otherwise.
+ */
+ public boolean isCreateConnectionComplete() {
+ return mIsCreateConnectionComplete;
+ }
+
+ @VisibleForTesting
+ public void setIsCreateConnectionComplete(boolean isCreateConnectionComplete) {
+ mIsCreateConnectionComplete = isCreateConnectionComplete;
+ }
+
@VisibleForTesting
public int getState() {
return mState;
@@ -1638,6 +1662,7 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
CallIdMapper idMapper,
ParcelableConnection connection) {
Log.v(this, "handleCreateConnectionSuccessful %s", connection);
+ mIsCreateConnectionComplete = true;
setTargetPhoneAccount(connection.getPhoneAccount());
setHandle(connection.getHandle(), connection.getHandlePresentation());
setCallerDisplayName(
diff --git a/src/com/android/server/telecom/ConnectionServiceWrapper.java b/src/com/android/server/telecom/ConnectionServiceWrapper.java
index 1b86842af..55ae0b6c8 100644
--- a/src/com/android/server/telecom/ConnectionServiceWrapper.java
+++ b/src/com/android/server/telecom/ConnectionServiceWrapper.java
@@ -34,6 +34,7 @@ import android.telecom.ConnectionService;
import android.telecom.DisconnectCause;
import android.telecom.GatewayInfo;
import android.telecom.Log;
+import android.telecom.Logging.Runnable;
import android.telecom.Logging.Session;
import android.telecom.ParcelableConference;
import android.telecom.ParcelableConnection;
@@ -57,6 +58,11 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
/**
* Wrapper for {@link IConnectionService}s, handles binding to {@link IConnectionService} and keeps
@@ -68,6 +74,12 @@ import java.util.concurrent.ConcurrentHashMap;
public class ConnectionServiceWrapper extends ServiceBinder implements
ConnectionServiceFocusManager.ConnectionServiceFocus {
+ private static final long SERVICE_BINDING_TIMEOUT = 15000L;
+ private ScheduledExecutorService mScheduledExecutor =
+ Executors.newSingleThreadScheduledExecutor();
+ // Pre-allocate space for 2 calls; realistically thats all we should ever need (tm)
+ private final Map<Call, ScheduledFuture<?>> mScheduledFutureMap = new ConcurrentHashMap<>(2);
+
private final class Adapter extends IConnectionServiceAdapter.Stub {
@Override
@@ -79,6 +91,12 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
try {
synchronized (mLock) {
logIncoming("handleCreateConnectionComplete %s", callId);
+ Call call = mCallIdMapper.getCall(callId);
+ if (mScheduledFutureMap.containsKey(call)) {
+ ScheduledFuture<?> existingTimeout = mScheduledFutureMap.get(call);
+ existingTimeout.cancel(false /* cancelIfRunning */);
+ mScheduledFutureMap.remove(call);
+ }
// Check status hints image for cross user access
if (connection.getStatusHints() != null) {
Icon icon = connection.getStatusHints().getIcon();
@@ -1027,7 +1045,8 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
* @param context The context.
* @param userHandle The {@link UserHandle} to use when binding.
*/
- ConnectionServiceWrapper(
+ @VisibleForTesting
+ public ConnectionServiceWrapper(
ComponentName componentName,
ConnectionServiceRepository connectionServiceRepository,
PhoneAccountRegistrar phoneAccountRegistrar,
@@ -1129,6 +1148,26 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
.setRttPipeToInCall(call.getCsToInCallRttPipeForCs())
.build();
+ Runnable r = new Runnable("CSW.cC", mLock) {
+ @Override
+ public void loggedRun() {
+ if (!call.isCreateConnectionComplete()) {
+ Log.e(this, new Exception(),
+ "Connection %s creation timeout",
+ getComponentName());
+ Log.addEvent(call, LogUtils.Events.CREATE_CONNECTION_TIMEOUT,
+ Log.piiHandle(call.getHandle()) + " via:" +
+ getComponentName().getPackageName());
+ response.handleCreateConnectionFailure(
+ new DisconnectCause(DisconnectCause.ERROR));
+ }
+ }
+ };
+ // Post cleanup to the executor service and cache the future, so we can cancel it if
+ // needed.
+ ScheduledFuture<?> future = mScheduledExecutor.schedule(r.getRunnableToCancel(),
+ SERVICE_BINDING_TIMEOUT, TimeUnit.MILLISECONDS);
+ mScheduledFutureMap.put(call, future);
try {
mServiceInterface.createConnection(
call.getConnectionManagerPhoneAccount(),
@@ -1414,7 +1453,8 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
}
}
- void addCall(Call call) {
+ @VisibleForTesting
+ public void addCall(Call call) {
if (mCallIdMapper.getCallId(call) == null) {
mCallIdMapper.addCall(call);
}
@@ -1778,4 +1818,9 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
private void noRemoteServices(RemoteServiceCallback callback) {
setRemoteServices(callback, Collections.EMPTY_LIST, Collections.EMPTY_LIST);
}
+
+ @VisibleForTesting
+ public void setScheduledExecutorService(ScheduledExecutorService service) {
+ mScheduledExecutor = service;
+ }
}
diff --git a/src/com/android/server/telecom/LogUtils.java b/src/com/android/server/telecom/LogUtils.java
index 02a3b7785..66efb5c92 100644
--- a/src/com/android/server/telecom/LogUtils.java
+++ b/src/com/android/server/telecom/LogUtils.java
@@ -86,6 +86,7 @@ public class LogUtils {
public static final String STOP_CALL_WAITING_TONE = "STOP_CALL_WAITING_TONE";
public static final String START_CONNECTION = "START_CONNECTION";
public static final String CREATE_CONNECTION_FAILED = "CREATE_CONNECTION_FAILED";
+ public static final String CREATE_CONNECTION_TIMEOUT = "CREATE_CONNECTION_TIMEOUT";
public static final String BIND_CS = "BIND_CS";
public static final String CS_BOUND = "CS_BOUND";
public static final String CONFERENCE_WITH = "CONF_WITH";
diff --git a/tests/src/com/android/server/telecom/tests/BasicCallTests.java b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
index 190604a75..810c01aa3 100644
--- a/tests/src/com/android/server/telecom/tests/BasicCallTests.java
+++ b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
@@ -927,6 +927,7 @@ public class BasicCallTests extends TelecomSystemTest {
call.setTargetPhoneAccount(mPhoneAccountA1.getAccountHandle());
assert(call.isVideoCallingSupported());
assertEquals(VideoProfile.STATE_BIDIRECTIONAL, call.getVideoState());
+ call.setIsCreateConnectionComplete(true);
}
/**
@@ -950,6 +951,7 @@ public class BasicCallTests extends TelecomSystemTest {
call.setTargetPhoneAccount(mPhoneAccountA2.getAccountHandle());
assert(!call.isVideoCallingSupported());
assertEquals(VideoProfile.STATE_AUDIO_ONLY, call.getVideoState());
+ call.setIsCreateConnectionComplete(true);
}
/**
diff --git a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
index ed2f6b19b..abc300555 100644
--- a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
@@ -31,6 +31,7 @@ import static org.mockito.Mockito.when;
import android.content.ComponentName;
import android.net.Uri;
+import android.os.IBinder;
import android.os.SystemClock;
import android.telecom.Connection;
import android.telecom.PhoneAccount;
@@ -44,11 +45,13 @@ import com.android.server.telecom.AsyncRingtonePlayer;
import com.android.server.telecom.Call;
import com.android.server.telecom.CallAudioManager;
import com.android.server.telecom.CallState;
+import com.android.internal.telecom.IConnectionService;
import com.android.server.telecom.CallerInfoAsyncQueryFactory;
import com.android.server.telecom.CallsManager;
import com.android.server.telecom.ClockProxy;
import com.android.server.telecom.ConnectionServiceFocusManager;
import com.android.server.telecom.ConnectionServiceFocusManager.ConnectionServiceFocusManagerFactory;
+import com.android.server.telecom.CreateConnectionResponse;
import com.android.server.telecom.ConnectionServiceWrapper;
import com.android.server.telecom.ContactsAsyncHelper;
import com.android.server.telecom.DefaultDialerCache;
@@ -140,6 +143,7 @@ public class CallsManagerTest extends TelecomTestCase {
@Mock private InCallController mInCallController;
@Mock private ConnectionServiceFocusManager mConnectionSvrFocusMgr;
@Mock private BluetoothStateReceiver mBluetoothStateReceiver;
+ @Mock private IConnectionService mIConnectionService;
private CallsManager mCallsManager;
@@ -190,8 +194,22 @@ public class CallsManagerTest extends TelecomTestCase {
eq(SIM_1_HANDLE), any())).thenReturn(SIM_1_ACCOUNT);
when(mPhoneAccountRegistrar.getPhoneAccount(
eq(SIM_2_HANDLE), any())).thenReturn(SIM_2_ACCOUNT);
+ when(mIConnectionService.asBinder()).thenReturn(mock(IBinder.class));
+
+ mComponentContextFixture.addConnectionService(new ComponentName(mContext.getPackageName(),
+ mContext.getPackageName().getClass().getName()), mIConnectionService);
}
+ @Override
+ @After
+ public void tearDown() throws Exception {
+ mComponentContextFixture.removeConnectionService(
+ new ComponentName(mContext.getPackageName(),
+ mContext.getPackageName().getClass().getName()),
+ mock(IConnectionService.class));
+ super.tearDown();
+ }
+
@MediumTest
@Test
public void testConstructPossiblePhoneAccounts() throws Exception {
@@ -684,6 +702,33 @@ public class CallsManagerTest extends TelecomTestCase {
assertEquals(CallState.ACTIVE, newCall.getState());
}
+
+ @Test
+ public void testConnectionServiceCreateConnectionTimeout() throws Exception {
+ ConnectionServiceWrapper service = new ConnectionServiceWrapper(new ComponentName(
+ mContext.getPackageName(), mContext.getPackageName().getClass().getName()), null,
+ mPhoneAccountRegistrar, mCallsManager, mContext, mLock, null);
+ TestScheduledExecutorService scheduledExecutorService = new TestScheduledExecutorService();
+ service.setScheduledExecutorService(scheduledExecutorService);
+ Call call = addSpyCall();
+ service.addCall(call);
+ when(call.isCreateConnectionComplete()).thenReturn(false);
+ CreateConnectionResponse response = mock(CreateConnectionResponse.class);
+
+ service.createConnection(call, response);
+ waitUntilConditionIsTrueOrTimeout(new Condition() {
+ @Override
+ public Object expected() {
+ return true;
+ }
+
+ @Override
+ public Object actual() {
+ return scheduledExecutorService.isRunnableScheduledAtTime(15000L);
+ }
+ }, 5000L, "Expected job failed to schedule");
+ }
+
private Call addSpyCallWithConnectionService(ConnectionServiceWrapper connSvr) {
Call call = addSpyCall();
doReturn(connSvr).when(call).getConnectionService();
@@ -739,4 +784,19 @@ public class CallsManagerTest extends TelecomTestCase {
when(mPhoneAccountRegistrar.getSimPhoneAccountsOfCurrentUser()).thenReturn(
new ArrayList<>(Arrays.asList(SIM_1_HANDLE, SIM_2_HANDLE)));
}
+
+ private void waitUntilConditionIsTrueOrTimeout(Condition condition, long timeout,
+ String description) throws InterruptedException {
+ final long start = System.currentTimeMillis();
+ while (!condition.expected().equals(condition.actual())
+ && System.currentTimeMillis() - start < timeout) {
+ sleep(50);
+ }
+ assertEquals(description, condition.expected(), condition.actual());
+ }
+
+ protected interface Condition {
+ Object expected();
+ Object actual();
+ }
}
diff --git a/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java b/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
index 01d312b98..86918a064 100644
--- a/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
+++ b/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
@@ -499,6 +499,14 @@ public class ComponentContextFixture implements TestFixture<Context> {
mServiceInfoByComponentName.put(componentName, serviceInfo);
}
+ public void removeConnectionService(
+ ComponentName componentName,
+ IConnectionService service)
+ throws Exception {
+ removeService(ConnectionService.SERVICE_INTERFACE, componentName, service);
+ mServiceInfoByComponentName.remove(componentName);
+ }
+
public void addInCallService(
ComponentName componentName,
IInCallService service)
@@ -541,6 +549,12 @@ public class ComponentContextFixture implements TestFixture<Context> {
mComponentNameByService.put(service, name);
}
+ private void removeService(String action, ComponentName name, IInterface service) {
+ mComponentNamesByAction.remove(action, name);
+ mServiceByComponentName.remove(name);
+ mComponentNameByService.remove(service);
+ }
+
private List<ResolveInfo> doQueryIntentServices(Intent intent, int flags) {
List<ResolveInfo> result = new ArrayList<>();
for (ComponentName componentName : mComponentNamesByAction.get(intent.getAction())) {
diff --git a/tests/src/com/android/server/telecom/tests/TestScheduledExecutorService.java b/tests/src/com/android/server/telecom/tests/TestScheduledExecutorService.java
new file mode 100644
index 000000000..8ddf42b9b
--- /dev/null
+++ b/tests/src/com/android/server/telecom/tests/TestScheduledExecutorService.java
@@ -0,0 +1,283 @@
+/*
+ * 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.server.telecom.tests;
+
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Delayed;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * A test implementation of a scheduled executor service.
+ */
+public class TestScheduledExecutorService implements ScheduledExecutorService {
+ private static final String TAG = "TestScheduledExecutorService";
+
+ private class CompletedFuture<T> implements Future<T>, ScheduledFuture<T> {
+
+ private final Callable<T> mTask;
+ private final long mDelayMs;
+ private Runnable mRunnable;
+
+ CompletedFuture(Callable<T> task) {
+ mTask = task;
+ mDelayMs = 0;
+ }
+
+ @SuppressWarnings("unused")
+ CompletedFuture(Callable<T> task, long delayMs) {
+ mTask = task;
+ mDelayMs = delayMs;
+ }
+
+ CompletedFuture(Runnable task, long delayMs) {
+ mRunnable = task;
+ mTask = (Callable<T>) Executors.callable(task);
+ mDelayMs = delayMs;
+ }
+
+ @Override
+ public boolean cancel(boolean mayInterruptIfRunning) {
+ cancelRunnable(mRunnable);
+ return true;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return false;
+ }
+
+ @Override
+ public boolean isDone() {
+ return true;
+ }
+
+ @Override
+ public T get() throws InterruptedException, ExecutionException {
+ try {
+ return mTask.call();
+ } catch (Exception e) {
+ throw new ExecutionException(e);
+ }
+ }
+
+ @Override
+ public T get(long timeout, TimeUnit unit)
+ throws InterruptedException, ExecutionException, TimeoutException {
+ try {
+ return mTask.call();
+ } catch (Exception e) {
+ throw new ExecutionException(e);
+ }
+ }
+
+ @Override
+ public long getDelay(TimeUnit unit) {
+ if (unit == TimeUnit.MILLISECONDS) {
+ return mDelayMs;
+ } else {
+ // not implemented
+ return 0;
+ }
+ }
+
+ @Override
+ public int compareTo(Delayed o) {
+ if (o == null) return 1;
+ if (o.getDelay(TimeUnit.MILLISECONDS) > mDelayMs) return -1;
+ if (o.getDelay(TimeUnit.MILLISECONDS) < mDelayMs) return 1;
+ return 0;
+ }
+ }
+
+ private long mClock = 0;
+ private Map<Long, Runnable> mScheduledRunnables = new HashMap<>();
+ private Map<Runnable, Long> mRepeatDuration = new HashMap<>();
+
+ @Override
+ public void shutdown() {
+ }
+
+ @Override
+ public List<Runnable> shutdownNow() {
+ return null;
+ }
+
+ @Override
+ public boolean isShutdown() {
+ return false;
+ }
+
+ @Override
+ public boolean isTerminated() {
+ return false;
+ }
+
+ @Override
+ public boolean awaitTermination(long timeout, TimeUnit unit) {
+ return false;
+ }
+
+ @Override
+ public <T> Future<T> submit(Callable<T> task) {
+ return new TestScheduledExecutorService.CompletedFuture<>(task);
+ }
+
+ @Override
+ public <T> Future<T> submit(Runnable task, T result) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public Future<?> submit(Runnable task) {
+ task.run();
+ return new TestScheduledExecutorService.CompletedFuture<>(() -> null);
+ }
+
+ @Override
+ public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout,
+ TimeUnit unit) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
+ // Schedule the runnable for execution at the specified time.
+ long scheduledTime = getNextExecutionTime(delay, unit);
+ mScheduledRunnables.put(scheduledTime, command);
+
+ Log.i(TAG, "schedule: runnable=" + System.identityHashCode(command) + ", time="
+ + scheduledTime);
+
+ return new TestScheduledExecutorService.CompletedFuture<Runnable>(command, delay);
+ }
+
+ @Override
+ public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period,
+ TimeUnit unit) {
+ return scheduleWithFixedDelay(command, initialDelay, period, unit);
+ }
+
+ @Override
+ public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay,
+ long delay, TimeUnit unit) {
+ // Schedule the runnable for execution at the specified time.
+ long nextScheduledTime = getNextExecutionTime(delay, unit);
+ mScheduledRunnables.put(nextScheduledTime, command);
+ mRepeatDuration.put(command, unit.toMillis(delay));
+
+ return new TestScheduledExecutorService.CompletedFuture<Runnable>(command, delay);
+ }
+
+ private long getNextExecutionTime(long delay, TimeUnit unit) {
+ long delayMillis = unit.toMillis(delay);
+ return mClock + delayMillis;
+ }
+
+ @Override
+ public void execute(Runnable command) {
+ command.run();
+ }
+
+ /**
+ * Used in unit tests, used to add a delta to the "clock" so that we can fire off scheduled
+ * items and reschedule the repeats.
+ * @param duration The duration (millis) to add to the clock.
+ */
+ public void advanceTime(long duration) {
+ Map<Long, Runnable> nextRepeats = new HashMap<>();
+ List<Runnable> toRun = new ArrayList<>();
+ mClock += duration;
+ Iterator<Map.Entry<Long, Runnable>> iterator = mScheduledRunnables.entrySet().iterator();
+ while (iterator.hasNext()) {
+ Map.Entry<Long, Runnable> entry = iterator.next();
+ if (mClock >= entry.getKey()) {
+ toRun.add(entry.getValue());
+
+ Runnable r = entry.getValue();
+ Log.i(TAG, "advanceTime: runningRunnable=" + System.identityHashCode(r));
+ // If this is a repeating scheduled item, schedule the repeat.
+ if (mRepeatDuration.containsKey(r)) {
+ // schedule next execution
+ nextRepeats.put(mClock + mRepeatDuration.get(r), entry.getValue());
+ }
+ iterator.remove();
+ }
+ }
+
+ // Update things at the end to avoid concurrent access.
+ mScheduledRunnables.putAll(nextRepeats);
+ toRun.forEach(r -> r.run());
+ }
+
+ /**
+ * Used from a {@link CompletedFuture} as defined above to cancel a scheduled task.
+ * @param r The runnable to cancel.
+ */
+ private void cancelRunnable(Runnable r) {
+ Optional<Map.Entry<Long, Runnable>> found = mScheduledRunnables.entrySet().stream()
+ .filter(e -> e.getValue() == r)
+ .findFirst();
+ if (found.isPresent()) {
+ mScheduledRunnables.remove(found.get().getKey());
+ }
+ mRepeatDuration.remove(r);
+ Log.i(TAG, "cancelRunnable: runnable=" + System.identityHashCode(r));
+ }
+
+ public int getNumberOfScheduledRunnables() {
+ return mScheduledRunnables.size();
+ }
+
+ public boolean isRunnableScheduledAtTime(long time) {
+ return mScheduledRunnables.containsKey(time);
+ }
+}
\ No newline at end of file

View File

@ -97,7 +97,7 @@ applyPatch "$DOS_PATCHES_COMMON/android_build/0001-verity-openssl3.patch"; #Fix
sed -i '74i$(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 's/PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION := 17/PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION := 28/' core/version_defaults.mk; #Set the minimum supported target SDK to Pie (GrapheneOS)
awk -i inplace '!/Email/' target/product/core.mk; #Remove Email
sed -i 's/2022-01-05/2024-08-05/' core/version_defaults.mk; #Bump Security String #P_asb_2024-08 #XXX
sed -i 's/2022-01-05/2024-09-05/' core/version_defaults.mk; #Bump Security String #P_asb_2024-09 #XXX
fi;
if enterAndClear "build/soong"; then
@ -135,7 +135,7 @@ applyPatch "$DOS_PATCHES/android_external_expat/338355.patch"; #P_asb_2022-09 Pr
applyPatch "$DOS_PATCHES/android_external_expat/338356.patch"; #P_asb_2022-09 Prevent more integer overflows
applyPatch "$DOS_PATCHES/android_external_expat/349328.patch"; #P_asb_2023-02 [CVE-2022-43680] Fix overeager DTD destruction (fixes #649)
applyPatch "$DOS_PATCHES/android_external_expat/0001-lib-Reject-negative-len-for-XML_ParseBuffer.patch";
applyPatch "$DOS_PATCHES/android_external_expat/0002-lib-Detect-integer-overflow-in-dtdCopy.patch.patch";
applyPatch "$DOS_PATCHES/android_external_expat/0002-lib-Detect-integer-overflow-in-dtdCopy.patch";
applyPatch "$DOS_PATCHES/android_external_expat/0003-lib-Detect-integer-overflow-in-function-nextScaffold.patch";
applyPatch "$DOS_PATCHES/android_external_expat/0004-lib-Stop-leaking-opening-tag-bindings-after-closing-.patch";
fi;
@ -204,6 +204,7 @@ applyPatch "$DOS_PATCHES/android_frameworks_av/379788.patch"; #P_asb_2024-01 Fix
applyPatch "$DOS_PATCHES/android_frameworks_av/383562.patch"; #P_asb_2024-02 Update mtp packet buffer
applyPatch "$DOS_PATCHES/android_frameworks_av/385670.patch"; #P_asb_2024-03 Validate OMX Params for VPx encoders
applyPatch "$DOS_PATCHES/android_frameworks_av/385671.patch"; #P_asb_2024-03 Fix out of bounds read and write in onQueueFilled in outQueue
applyPatch "$DOS_PATCHES/android_frameworks_av/402601.patch"; #Q_asb_2024-08 Fix flag check in JAudioTrack.cpp
applyPatch "$DOS_PATCHES/android_frameworks_av/399771.patch"; #P_asb_2024-08 StagefrightRecoder: Disabling B-frame support
applyPatch "$DOS_PATCHES/android_frameworks_av/0001-HM-No_RLIMIT_AS.patch"; #(GrapheneOS)
fi;
@ -337,6 +338,7 @@ applyPatch "$DOS_PATCHES/android_frameworks_base/397594.patch"; #P_asb_2024-07 V
applyPatch "$DOS_PATCHES/android_frameworks_base/397595.patch"; #P_asb_2024-07 Fix security vulnerability of non-dynamic permission removal
applyPatch "$DOS_PATCHES/android_frameworks_base/399769.patch"; #P_asb_2024-08 Restrict USB poups while setup is in progress
applyPatch "$DOS_PATCHES/android_frameworks_base/399770.patch"; #P_asb_2024-08 Hide SAW subwindows
applyPatch "$DOS_PATCHES/android_frameworks_base/401373-backport.patch"; #S_asb_2024-09 Sanitized uri scheme by removing scheme delimiter
applyPatch "$DOS_PATCHES/android_frameworks_base/0007-Always_Restict_Serial.patch"; #Always restrict access to Build.SERIAL (GrapheneOS)
applyPatch "$DOS_PATCHES/android_frameworks_base/0008-Browser_No_Location.patch"; #Don't grant location permission to system browsers (GrapheneOS)
applyPatch "$DOS_PATCHES/android_frameworks_base/0009-SystemUI_No_Permission_Review.patch"; #Allow SystemUI to directly manage Bluetooth/WiFi (GrapheneOS)
@ -539,7 +541,9 @@ applyPatch "$DOS_PATCHES/android_packages_apps_Settings/351915.patch"; #P_asb_20
applyPatch "$DOS_PATCHES/android_packages_apps_Settings/359734.patch"; #P_asb_2023-06 Convert argument to intent in AddAccountSettings.
applyPatch "$DOS_PATCHES/android_packages_apps_Settings/366136.patch"; #P_asb_2023-09 Prevent non-system IME from becoming device admin
applyPatch "$DOS_PATCHES/android_packages_apps_Settings/370700.patch"; #P_asb_2023-10 Restrict ApnEditor settings
applyPatch "$DOS_PATCHES/android_packages_apps_Settings/316891059-16.patch"; #x-asb_2024-05 Replace getCallingActivity() with getLaunchedFromPackage()
applyPatch "$DOS_PATCHES/android_packages_apps_Settings/401375-backport.patch"; #S_asb_2024-09 Limit wifi item edit content's max length to 500
applyPatch "$DOS_PATCHES/android_packages_apps_Settings/401376-backport.patch"; #S_asb_2024-09 Replace getCallingActivity() with getLaunchedFromPackage()
applyPatch "$DOS_PATCHES/android_packages_apps_Settings/401377-backport.patch"; #S_asb_2024-09 Ignore fragment attr from ext authenticator resource
git revert --no-edit c240992b4c86c7f226290807a2f41f2619e7e5e8; #Don't hide OEM unlock
applyPatch "$DOS_PATCHES/android_packages_apps_Settings/0001-Captive_Portal_Toggle.patch"; #Add option to disable captive portal checks (MSe1969)
#applyPatch "$DOS_PATCHES/android_packages_apps_Settings/0004-Private_DNS.patch"; #More 'Private DNS' options (heavily based off of a CalyxOS patch) #TODO: Needs work
@ -611,6 +615,7 @@ applyPatch "$DOS_PATCHES/android_packages_services_Telecomm/347042.patch"; #P_as
applyPatch "$DOS_PATCHES/android_packages_services_Telecomm/356150.patch"; #P_asb_2023-05 enforce stricter rules when registering phoneAccounts
applyPatch "$DOS_PATCHES/android_packages_services_Telecomm/364617.patch"; #P_asb_2023-08 Resolve StatusHints image exploit across user.
applyPatch "$DOS_PATCHES/android_packages_services_Telecomm/377776.patch"; #P_asb_2023-12 Resolve account image icon profile boundary exploit.
applyPatch "$DOS_PATCHES/android_packages_services_Telecomm/401380-backport.patch"; #S_asb_2024-09 Unbind CS if connection is not created within 15 seconds. #XXX
fi;
if enterAndClear "packages/services/Telephony"; then