18.1: September 2024 ASB work

Signed-off-by: Tavi <tavi@divested.dev>
This commit is contained in:
Tavi 2024-09-14 12:44:16 -04:00
parent a4f9a76fb9
commit 5c166d2039
No known key found for this signature in database
GPG Key ID: E599F62ECBAEAF2E
15 changed files with 1110 additions and 13 deletions

View File

@ -135,7 +135,7 @@ external/cblas d82c5f4ae14b2a5468303985070f7dadc15d4094
external/cbor-java f81e576298790c97498311e99a0b0b34653c3dd8 external/cbor-java f81e576298790c97498311e99a0b0b34653c3dd8
external/chromium-libpac 169c93e00a00605346a68d39d3f4713735bdb61e external/chromium-libpac 169c93e00a00605346a68d39d3f4713735bdb61e
external/chromium-trace e524766cad26d677a9a1ec8c00c512d4cac2cf5e external/chromium-trace e524766cad26d677a9a1ec8c00c512d4cac2cf5e
external/chromium-webview b270aa98312408d5893ee72fcd62b4d89937ceb2 external/chromium-webview 8400ae9b819741cd4d436cce372496426ec85fc9
external/clang 0a1c53a5d295109bd4702ad13c0f2a5510ca1b26 external/clang 0a1c53a5d295109bd4702ad13c0f2a5510ca1b26
external/cldr 38850463abd624d5b2293be75fddc43cf6b55ae2 external/cldr 38850463abd624d5b2293be75fddc43cf6b55ae2
external/cn-cbor 696530332036f5518681d3c450cdbc3ee412004a external/cn-cbor 696530332036f5518681d3c450cdbc3ee412004a

View File

@ -9,10 +9,10 @@ Reported by TaiYou
1 file changed, 6 insertions(+) 1 file changed, 6 insertions(+)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index 381f3ef..97440d8 100644 index c84b5ed..02f71c4 100644
--- a/lib/xmlparse.c --- a/lib/xmlparse.c
+++ b/lib/xmlparse.c +++ b/lib/xmlparse.c
@@ -1883,6 +1883,12 @@ XML_ParseBuffer(XML_Parser parser, int len, int isFinal) { @@ -1874,6 +1874,12 @@ XML_ParseBuffer(XML_Parser parser, int len, int isFinal) {
if (parser == NULL) if (parser == NULL)
return XML_STATUS_ERROR; return XML_STATUS_ERROR;

View File

@ -9,10 +9,10 @@ Reported by TaiYou
1 file changed, 10 insertions(+) 1 file changed, 10 insertions(+)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index 97440d8..9bd93b0 100644 index 02f71c4..18fcad0 100644
--- a/lib/xmlparse.c --- a/lib/xmlparse.c
+++ b/lib/xmlparse.c +++ b/lib/xmlparse.c
@@ -6377,6 +6377,16 @@ dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, @@ -6358,6 +6358,16 @@ dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
if (! newE) if (! newE)
return 0; return 0;
if (oldE->nDefaultAtts) { if (oldE->nDefaultAtts) {

View File

@ -9,10 +9,10 @@ Reported by TaiYou
1 file changed, 9 insertions(+) 1 file changed, 9 insertions(+)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index 9bd93b0..e6f334a 100644 index 18fcad0..b08cae9 100644
--- a/lib/xmlparse.c --- a/lib/xmlparse.c
+++ b/lib/xmlparse.c +++ b/lib/xmlparse.c
@@ -6929,6 +6929,15 @@ nextScaffoldPart(XML_Parser parser) { @@ -6910,6 +6910,15 @@ nextScaffoldPart(XML_Parser parser) {
int next; int next;
if (! dtd->scaffIndex) { if (! dtd->scaffIndex) {

View File

@ -11,10 +11,10 @@ Subject: [PATCH] lib: Stop leaking opening tag bindings after closing tag
1 file changed, 3 insertions(+), 3 deletions(-) 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index e6f334a..602fa33 100644 index b08cae9..f2c245d 100644
--- a/lib/xmlparse.c --- a/lib/xmlparse.c
+++ b/lib/xmlparse.c +++ b/lib/xmlparse.c
@@ -2847,9 +2847,6 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, @@ -2828,9 +2828,6 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
int len; int len;
const char *rawName; const char *rawName;
TAG *tag = parser->m_tagStack; TAG *tag = parser->m_tagStack;
@ -24,7 +24,7 @@ index e6f334a..602fa33 100644
rawName = s + enc->minBytesPerChar * 2; rawName = s + enc->minBytesPerChar * 2;
len = XmlNameLength(enc, rawName); len = XmlNameLength(enc, rawName);
if (len != tag->rawNameLength if (len != tag->rawNameLength
@@ -2857,6 +2854,9 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, @@ -2838,6 +2835,9 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
*eventPP = rawName; *eventPP = rawName;
return XML_ERROR_TAG_MISMATCH; return XML_ERROR_TAG_MISMATCH;
} }

View File

@ -0,0 +1,34 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Wonsik Kim <wonsik@google.com>
Date: Fri, 28 Jun 2024 00:33:51 +0000
Subject: [PATCH] omx: check HDR10+ info param size
Bug: 329641908
Test: presubmit
Flag: EXEMPT security fix
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:53298956ba6bb8f147a632d7aaed8566dfc203ee)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:f816148a719d2a3bbf432f11da98b3d5fa7de74f)
Merged-In: I72523e1de61e5f947174272b732e170e1c2964df
Change-Id: I72523e1de61e5f947174272b732e170e1c2964df
---
media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
index 418302389d..4ab5d10609 100644
--- a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
@@ -619,6 +619,13 @@ OMX_ERRORTYPE SoftVideoDecoderOMXComponent::getConfig(
if (!isValidOMXParam(outParams)) {
return OMX_ErrorBadParameter;
}
+ if (offsetof(DescribeHDR10PlusInfoParams, nValue) + outParams->nParamSize >
+ outParams->nSize) {
+ ALOGE("b/329641908: too large param size; nParamSize=%u nSize=%u",
+ outParams->nParamSize, outParams->nSize);
+ android_errorWriteLog(0x534e4554, "329641908");
+ return OMX_ErrorBadParameter;
+ }
outParams->nParamSizeUsed = info->size();

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 84fc4f78edc4..4446f09bc874 100644
--- a/core/java/android/net/Uri.java
+++ b/core/java/android/net/Uri.java
@@ -1380,7 +1380,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 670aefd21d36..17a37831afdb 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 androidx.test.filters.SmallTest;
@@ -88,6 +89,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 88760723883..2ce29040f0d 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -147,6 +147,7 @@
<item name="android:textAppearance">@android:style/TextAppearance.DeviceDefault.Medium</item>
<item name="android:textColorHint">?android:attr/textColorSecondary</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 diff --git a/src/com/android/settings/search/SearchFeatureProvider.java b/src/com/android/settings/search/SearchFeatureProvider.java
index 20d4e7c16bd..d6950eb06aa 100644 index 20d4e7c16bd..d6950eb06aa 100644
--- a/src/com/android/settings/search/SearchFeatureProvider.java --- a/src/com/android/settings/search/SearchFeatureProvider.java
@ -12,7 +35,7 @@ index 20d4e7c16bd..d6950eb06aa 100644
/** /**
diff --git a/src/com/android/settings/search/SearchFeatureProviderImpl.java b/src/com/android/settings/search/SearchFeatureProviderImpl.java diff --git a/src/com/android/settings/search/SearchFeatureProviderImpl.java b/src/com/android/settings/search/SearchFeatureProviderImpl.java
index 63bf420c027..eaadbc2af50 100644 index 63bf420c027..423779fbabf 100644
--- a/src/com/android/settings/search/SearchFeatureProviderImpl.java --- a/src/com/android/settings/search/SearchFeatureProviderImpl.java
+++ b/src/com/android/settings/search/SearchFeatureProviderImpl.java +++ b/src/com/android/settings/search/SearchFeatureProviderImpl.java
@@ -17,13 +17,14 @@ @@ -17,13 +17,14 @@

View File

@ -0,0 +1,111 @@
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 | 55 +++++++++++++++++++
1 file changed, 55 insertions(+)
diff --git a/src/com/android/settings/accounts/AccountTypePreferenceLoader.java b/src/com/android/settings/accounts/AccountTypePreferenceLoader.java
index c639d1df2eb..84386a38f08 100644
--- a/src/com/android/settings/accounts/AccountTypePreferenceLoader.java
+++ b/src/com/android/settings/accounts/AccountTypePreferenceLoader.java
@@ -32,6 +32,10 @@ import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+import androidx.collection.ArraySet;
import androidx.preference.Preference;
import androidx.preference.Preference.OnPreferenceClickListener;
import androidx.preference.PreferenceFragmentCompat;
@@ -45,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.
@@ -83,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
@@ -98,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);
@@ -182,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,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Chris Antol <cantol@google.com>
Date: Mon, 25 Mar 2024 23:49:35 +0000
Subject: [PATCH] RESTRICT AUTOMERGE Restrict Settings Homepage prior to
provisioning
Bug: 327749022
Test: manual test
1. factory reset + launch Settings via ADB during Setup -> verify app closes
2. factory reset + bypass Setup + tap Settings icon in launcher -> verify app closes
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:70a5a0fd353cc6203d2926627de93786155ae5bc)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:7f1c4df02d153cb380a6147e86194bec2a564ab7)
Merged-In: I8cbe38109ebf88a0f68f3917e95468a81c6463c1
Change-Id: I8cbe38109ebf88a0f68f3917e95468a81c6463c1
---
.../settings/homepage/SettingsHomepageActivity.java | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/src/com/android/settings/homepage/SettingsHomepageActivity.java b/src/com/android/settings/homepage/SettingsHomepageActivity.java
index a8426437f57..d9f3c31ed22 100644
--- a/src/com/android/settings/homepage/SettingsHomepageActivity.java
+++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java
@@ -43,6 +43,16 @@ public class SettingsHomepageActivity extends FragmentActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ // Ensure device is provisioned in order to access Settings home
+ // TODO(b/331254029): This should later be replaced in favor of an allowlist
+ boolean unprovisioned = android.provider.Settings.Global.getInt(getContentResolver(),
+ android.provider.Settings.Global.DEVICE_PROVISIONED, 0) == 0;
+ if (unprovisioned) {
+ Log.e("SettingsHomepageActivity", "Device is not provisioned, exiting Settings");
+ finish();
+ return;
+ }
+
setContentView(R.layout.settings_homepage_container);
final View root = findViewById(R.id.settings_homepage_container);
root.setSystemUiVisibility(

View File

@ -0,0 +1,702 @@
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 | 26 ++
.../telecom/ConnectionServiceWrapper.java | 74 ++++-
src/com/android/server/telecom/LogUtils.java | 2 +
.../server/telecom/tests/BasicCallTests.java | 2 +
.../telecom/tests/CallsManagerTest.java | 54 ++++
.../tests/ComponentContextFixture.java | 14 +
.../tests/TestScheduledExecutorService.java | 283 ++++++++++++++++++
7 files changed, 453 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 cd236d2f4..e8c5a47ac 100755
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -329,6 +329,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;
@@ -958,6 +969,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;
@@ -2043,6 +2067,7 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
CallIdMapper idMapper,
ParcelableConference conference) {
Log.v(this, "handleCreateConferenceSuccessful %s", conference);
+ mIsCreateConnectionComplete = true;
setTargetPhoneAccount(conference.getPhoneAccount());
setHandle(conference.getHandle(), conference.getHandlePresentation());
@@ -2076,6 +2101,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 64fdd8833..6ca74fba3 100644
--- a/src/com/android/server/telecom/ConnectionServiceWrapper.java
+++ b/src/com/android/server/telecom/ConnectionServiceWrapper.java
@@ -37,6 +37,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;
@@ -59,6 +60,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
@@ -72,6 +78,11 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
private static final String TELECOM_ABBREVIATION = "cast";
+ 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
@@ -84,6 +95,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();
@@ -120,6 +137,12 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
try {
synchronized (mLock) {
logIncoming("handleCreateConferenceComplete %s", callId);
+ Call call = mCallIdMapper.getCall(callId);
+ if (mScheduledFutureMap.containsKey(call)) {
+ ScheduledFuture<?> existingTimeout = mScheduledFutureMap.get(call);
+ existingTimeout.cancel(false /* cancelIfRunning */);
+ mScheduledFutureMap.remove(call);
+ }
ConnectionServiceWrapper.this
.handleCreateConferenceComplete(callId, request, conference);
@@ -1183,7 +1206,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,
@@ -1258,6 +1282,26 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
.setIsAdhocConferenceCall(call.isAdhocConferenceCall())
.build();
+ Runnable r = new Runnable("CSW.cC", mLock) {
+ @Override
+ public void loggedRun() {
+ if (!call.isCreateConnectionComplete()) {
+ Log.e(this, new Exception(),
+ "Conference %s creation timeout",
+ getComponentName());
+ Log.addEvent(call, LogUtils.Events.CREATE_CONFERENCE_TIMEOUT,
+ Log.piiHandle(call.getHandle()) + " via:" +
+ getComponentName().getPackageName());
+ response.handleCreateConferenceFailure(
+ 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.createConference(
call.getConnectionManagerPhoneAccount(),
@@ -1347,6 +1391,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(),
@@ -1727,7 +1791,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);
}
@@ -2172,4 +2237,9 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
sb.append("]");
return sb.toString();
}
+
+ @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 5bb14e625..1c62a5c71 100644
--- a/src/com/android/server/telecom/LogUtils.java
+++ b/src/com/android/server/telecom/LogUtils.java
@@ -124,8 +124,10 @@ 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 START_CONFERENCE = "START_CONFERENCE";
public static final String CREATE_CONFERENCE_FAILED = "CREATE_CONFERENCE_FAILED";
+ public static final String CREATE_CONFERENCE_TIMEOUT = "CREATE_CONFERENCE_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 382e0b710..6ac8e1c62 100644
--- a/tests/src/com/android/server/telecom/tests/BasicCallTests.java
+++ b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
@@ -963,6 +963,7 @@ public class BasicCallTests extends TelecomSystemTest {
call.setTargetPhoneAccount(mPhoneAccountA1.getAccountHandle());
assert(call.isVideoCallingSupportedByPhoneAccount());
assertEquals(VideoProfile.STATE_BIDIRECTIONAL, call.getVideoState());
+ call.setIsCreateConnectionComplete(true);
}
/**
@@ -986,6 +987,7 @@ public class BasicCallTests extends TelecomSystemTest {
call.setTargetPhoneAccount(mPhoneAccountA2.getAccountHandle());
assert(!call.isVideoCallingSupportedByPhoneAccount());
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 d16430298..912b56cf3 100644
--- a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
@@ -40,11 +40,13 @@ import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import static java.lang.Thread.sleep;
import android.content.ComponentName;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
+import android.os.IBinder;
import android.os.Process;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -62,6 +64,7 @@ import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;
import android.widget.Toast;
+import com.android.internal.telecom.IConnectionService;
import com.android.server.telecom.AsyncRingtonePlayer;
import com.android.server.telecom.Call;
import com.android.server.telecom.CallAudioManager;
@@ -74,6 +77,7 @@ import com.android.server.telecom.CallsManagerListenerBase;
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.DefaultDialerCache;
import com.android.server.telecom.EmergencyCallHelper;
import com.android.server.telecom.HeadsetMediaButton;
@@ -207,6 +211,7 @@ public class CallsManagerTest extends TelecomTestCase {
@Mock private IncomingCallFilter mIncomingCallFilter;
@Mock private ToastFactory mToastFactory;
@Mock private Toast mToast;
+ @Mock private IConnectionService mIConnectionService;
private CallsManager mCallsManager;
@@ -274,11 +279,19 @@ public class CallsManagerTest extends TelecomTestCase {
eq(SIM_2_HANDLE), any())).thenReturn(SIM_2_ACCOUNT);
when(mToastFactory.makeText(any(), anyInt(), anyInt())).thenReturn(mToast);
when(mToastFactory.makeText(any(), any(), anyInt())).thenReturn(mToast);
+ 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();
}
@@ -1456,6 +1469,32 @@ public class CallsManagerTest extends TelecomTestCase {
assertTrue(argumentCaptor.getValue().contains("Unavailable phoneAccountHandle"));
}
+ @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 addSpyCall() {
return addSpyCall(SIM_2_HANDLE, CallState.ACTIVE);
}
@@ -1549,4 +1588,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 af062d77f..0768970b1 100644
--- a/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
+++ b/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
@@ -589,6 +589,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,
@@ -658,6 +666,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

@ -0,0 +1,43 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Pranav Madapurmath <pmadapurmath@google.com>
Date: Tue, 11 Jun 2024 15:51:39 +0000
Subject: [PATCH] Unbind CallScreeningService when timeout reached.
In a vulnerability, the exploiter showed that an app which implements a
service with role holding ROLE_CALL_SCREENING can be used to keep a
service alive. The assumption is that the CallScreeningService class
uses MSG_SCREEN_CALL to screen the call and results in the service being
unbound for outgoing calls once screening completes. However, a vanilla
service which holds the ROLE_CALL_SCREENING role can still be used as
the default call screening app which keeps the service alive.
This CL ensures that after the timeout is reached that we try to unbind
the service if possible.
Bug: 300904123
Test: Manual test to verify that onDestroy is called for the service
after the timeout is reached.
(cherry picked from commit 9d97cd5825066ac8e15bbf97f6755663c5341afb)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:d57f25311acb7fb887fb0296364526345cc905bb)
Merged-In: I30d276867c571ece113106d3b363fce99d64f441
Change-Id: I30d276867c571ece113106d3b363fce99d64f441
---
.../android/server/telecom/CallScreeningServiceHelper.java | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/com/android/server/telecom/CallScreeningServiceHelper.java b/src/com/android/server/telecom/CallScreeningServiceHelper.java
index 5e47c1f94..e9ad451c2 100644
--- a/src/com/android/server/telecom/CallScreeningServiceHelper.java
+++ b/src/com/android/server/telecom/CallScreeningServiceHelper.java
@@ -191,6 +191,10 @@ public class CallScreeningServiceHelper {
Log.w(TAG, "Cancelling call id process due to timeout");
}
mFuture.complete(null);
+ mContext.unbindService(serviceConnection);
+ } catch (IllegalArgumentException e) {
+ Log.i(this, "Exception when unbinding service %s : %s", serviceConnection,
+ e.getMessage());
} finally {
Log.endSession();
}

View File

@ -0,0 +1,40 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Pranav Madapurmath <pmadapurmath@google.com>
Date: Tue, 11 Jun 2024 22:50:08 -0700
Subject: [PATCH] Resolve cross-user image exploit for conference status hints
Ensure that status hint image icon is validated for cross-user exploits.
Currently, there is no check for this so a conference call can display
an image from another user, exposing a vulnerability.
Bug: 329058967
Test: Manual with POC
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:a8e2bf9c77cd94f683979c849015b78ef0537802)
Merged-In: Ib9d701398d25d021cdb9abacbaa5b175f62bee1d
Change-Id: Ib9d701398d25d021cdb9abacbaa5b175f62bee1d
---
.../android/server/telecom/ConnectionServiceWrapper.java | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/com/android/server/telecom/ConnectionServiceWrapper.java b/src/com/android/server/telecom/ConnectionServiceWrapper.java
index 6ca74fba3..e944209a4 100644
--- a/src/com/android/server/telecom/ConnectionServiceWrapper.java
+++ b/src/com/android/server/telecom/ConnectionServiceWrapper.java
@@ -133,10 +133,17 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
ParcelableConference conference, Session.Info sessionInfo) {
Log.startSession(sessionInfo, LogUtils.Sessions.CSW_HANDLE_CREATE_CONNECTION_COMPLETE,
mPackageAbbreviation);
+ UserHandle callingUserHandle = Binder.getCallingUserHandle();
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
logIncoming("handleCreateConferenceComplete %s", callId);
+ // Check status hints image for cross user access
+ if (conference.getStatusHints() != null) {
+ Icon icon = conference.getStatusHints().getIcon();
+ conference.getStatusHints().setIcon(StatusHints.
+ validateAccountIconUserBoundary(icon, callingUserHandle));
+ }
Call call = mCallIdMapper.getCall(callId);
if (mScheduledFutureMap.containsKey(call)) {
ScheduledFuture<?> existingTimeout = mScheduledFutureMap.get(call);

View File

@ -93,7 +93,7 @@ applyPatch "$DOS_PATCHES_COMMON/android_build/0001-verity-openssl3.patch"; #Fix
sed -i '75i$(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 '75i$(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 '!/updatable_apex.mk/' target/product/mainline_system.mk; #Disable APEX awk -i inplace '!/updatable_apex.mk/' target/product/mainline_system.mk; #Disable APEX
sed -i 's/PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION := 23/PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION := 28/' core/version_defaults.mk; #Set the minimum supported target SDK to Pie (GrapheneOS) sed -i 's/PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION := 23/PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION := 28/' core/version_defaults.mk; #Set the minimum supported target SDK to Pie (GrapheneOS)
sed -i 's/2024-02-05/2024-08-05/' core/version_defaults.mk; #Bump Security String #R_asb_2024-08 sed -i 's/2024-02-05/2024-09-05/' core/version_defaults.mk; #Bump Security String #R_asb_2024-09
fi; fi;
if enterAndClear "build/soong"; then if enterAndClear "build/soong"; then
@ -141,6 +141,7 @@ applyPatch "$DOS_PATCHES/android_frameworks_av/385529.patch"; #R_asb_2024-03 Val
applyPatch "$DOS_PATCHES/android_frameworks_av/385530.patch"; #R_asb_2024-03 SoftVideoDecodeOMXComponent: validate OMX params for dynamic HDR applyPatch "$DOS_PATCHES/android_frameworks_av/385530.patch"; #R_asb_2024-03 SoftVideoDecodeOMXComponent: validate OMX params for dynamic HDR
applyPatch "$DOS_PATCHES/android_frameworks_av/385531.patch"; #R_asb_2024-03 Fix out of bounds read and write in onQueueFilled in outQueue applyPatch "$DOS_PATCHES/android_frameworks_av/385531.patch"; #R_asb_2024-03 Fix out of bounds read and write in onQueueFilled in outQueue
applyPatch "$DOS_PATCHES/android_frameworks_av/399741.patch"; #R_asb_2024-08 StagefrightRecoder: Disabling B-frame support applyPatch "$DOS_PATCHES/android_frameworks_av/399741.patch"; #R_asb_2024-08 StagefrightRecoder: Disabling B-frame support
applyPatch "$DOS_PATCHES/android_frameworks_av/401372.patch"; #S_asb_2024-09 omx: check HDR10+ info param size
fi; fi;
if enterAndClear "frameworks/base"; then if enterAndClear "frameworks/base"; then
@ -172,6 +173,7 @@ applyPatch "$DOS_PATCHES/android_frameworks_base/397543.patch"; #R_asb_2024-07 F
applyPatch "$DOS_PATCHES/android_frameworks_base/399738.patch"; #R_asb_2024-08 Backport preventing BAL bypass via bound service applyPatch "$DOS_PATCHES/android_frameworks_base/399738.patch"; #R_asb_2024-08 Backport preventing BAL bypass via bound service
applyPatch "$DOS_PATCHES/android_frameworks_base/399739.patch"; #R_asb_2024-08 Restrict USB poups while setup is in progress applyPatch "$DOS_PATCHES/android_frameworks_base/399739.patch"; #R_asb_2024-08 Restrict USB poups while setup is in progress
applyPatch "$DOS_PATCHES/android_frameworks_base/399740.patch"; #R_asb_2024-08 Hide SAW subwindows applyPatch "$DOS_PATCHES/android_frameworks_base/399740.patch"; #R_asb_2024-08 Hide SAW subwindows
applyPatch "$DOS_PATCHES/android_frameworks_base/401373.patch"; #S_asb_2024-09 Sanitized uri scheme by removing scheme delimiter
git revert --no-edit 438d9feacfcad73d3ee918541574132928a93644; #Reverts "Allow signature spoofing for microG Companion/Services" in favor of below patch git revert --no-edit 438d9feacfcad73d3ee918541574132928a93644; #Reverts "Allow signature spoofing for microG Companion/Services" in favor of below patch
applyPatch "$DOS_PATCHES/android_frameworks_base/0007-Always_Restict_Serial.patch"; #Always restrict access to Build.SERIAL (GrapheneOS) 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/0008-Browser_No_Location.patch"; #Don't grant location permission to system browsers (GrapheneOS)
@ -366,7 +368,10 @@ applyPatch "$DOS_PATCHES/android_packages_apps_PermissionController/0002-Special
fi; fi;
if enterAndClear "packages/apps/Settings"; then if enterAndClear "packages/apps/Settings"; then
applyPatch "$DOS_PATCHES/android_packages_apps_Settings/316891059-18.patch"; #x-asb_2024-05 Replace getCallingActivity() with getLaunchedFromPackage() applyPatch "$DOS_PATCHES/android_packages_apps_Settings/401375.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.patch"; #S_asb_2024-09 Ignore fragment attr from ext authenticator resource
applyPatch "$DOS_PATCHES/android_packages_apps_Settings/401378-backport.patch"; #S_asb_2024-09 Restrict Settings Homepage prior to provisioning
#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/0001-Captive_Portal_Toggle.patch"; #Add option to disable captive portal checks (MSe1969)
applyPatch "$DOS_PATCHES/android_packages_apps_Settings/0001-Captive_Portal_Toggle-gos.patch"; #Add option to disable captive portal checks (GrapheneOS) applyPatch "$DOS_PATCHES/android_packages_apps_Settings/0001-Captive_Portal_Toggle-gos.patch"; #Add option to disable captive portal checks (GrapheneOS)
applyPatch "$DOS_PATCHES/android_packages_apps_Settings/0003-Remove_SensorsOff_Tile.patch"; #Remove the Sensors Off development tile (DivestOS) applyPatch "$DOS_PATCHES/android_packages_apps_Settings/0003-Remove_SensorsOff_Tile.patch"; #Remove the Sensors Off development tile (DivestOS)
@ -433,6 +438,12 @@ applyPatch "$DOS_PATCHES/android_packages_providers_TelephonyProvider/304614.pat
applyPatch "$DOS_PATCHES/android_packages_providers_TelephonyProvider/312102.patch"; #mnc fix (Sony) applyPatch "$DOS_PATCHES/android_packages_providers_TelephonyProvider/312102.patch"; #mnc fix (Sony)
fi; fi;
if enterAndClear "packages/services/Telecomm"; then
applyPatch "$DOS_PATCHES/android_packages_services_Telecomm/401380-backport.patch"; #S_asb_2024-09 Unbind CS if connection is not created within 15 seconds.
applyPatch "$DOS_PATCHES/android_packages_services_Telecomm/401381.patch"; #S_asb_2024-09 Unbind CallScreeningService when timeout reached.
applyPatch "$DOS_PATCHES/android_packages_services_Telecomm/401382.patch"; #S_asb_2024-09 Resolve cross-user image exploit for conference status hints
fi;
if enterAndClear "packages/services/Telephony"; then if enterAndClear "packages/services/Telephony"; then
if [ -d "$DOS_BUILD_BASE"/vendor/divested-carriersettings ]; then applyPatch "$DOS_PATCHES/android_packages_services_Telephony/0001-CC2.patch"; fi; #Runtime control of platform carrier config package (DivestOS) if [ -d "$DOS_BUILD_BASE"/vendor/divested-carriersettings ]; then applyPatch "$DOS_PATCHES/android_packages_services_Telephony/0001-CC2.patch"; fi; #Runtime control of platform carrier config package (DivestOS)
fi; fi;