CVE-2026-49881 AI-generated analysis
platform/packages/services/Telecomm (InCallController) and platform/frameworks/base (core/res/AndroidManifest.xml), Telecom InCallService binding
Removes InCallController.serviceClassExists and the 'android.telecom.CLASS_EXISTENCE_CHECK' metadata check from Telecom. That code loaded a third-party package's code inside Telecom during InCallService enumeration (CONTEXT_INCLUDE_CODE | CONTEXT_IGNORE_SECURITY, then getClassLoader and Class.forName). The fix also drops the now-unused metadata from ConnectivityCallListenerService in the framework manifest.
Root cause
InCallController.getInCallServiceComponents() enumerated InCallService components with queryIntentServices(GET_META_DATA | MATCH_DISABLED_COMPONENTS). For any entry whose ServiceInfo.metaData had 'android.telecom.CLASS_EXISTENCE_CHECK' = true, it called serviceClassExists(). That method called mContext.createPackageContextAsUser(serviceInfo.packageName, CONTEXT_INCLUDE_CODE | CONTEXT_IGNORE_SECURITY, userHandle), then packageContext.getClassLoader() and Class.forName(serviceInfo.name, false, classLoader). The app that declared the InCallService controlled both the metadata flag and the package, so Telecom loaded that app's code into its own process. Per the commit message, this allowed arbitrary code execution in system_server through a custom AppComponentFactory. In the diff, the check is the first statement inside the 'serviceInfo != null' block of the loop.
How the fix works
- packages/services/Telecomm 668eb07260ec, src/com/android/server/telecom/InCallController.java: deletes the private method serviceClassExists(ServiceInfo, UserHandle) entirely. This removes the createPackageContextAsUser(..., CONTEXT_INCLUDE_CODE | CONTEXT_IGNORE_SECURITY, ...), getClassLoader(), Class.forName() sequence.
- Same commit, InCallController.getInCallServiceComponents(): removes the isMetaFlag computation that read 'android.telecom.CLASS_EXISTENCE_CHECK' from serviceInfo.metaData, and the 'if (isMetaFlag && !serviceClassExists(...)) continue;' early skip. The loop now goes straight to the existing METADATA_INCLUDE_EXTERNAL_CALLS handling. Per the commit message, Telecom now relies on standard binding mechanisms, which do not execute third-party code during component resolution.
- Same commit, tests/src/com/android/server/telecom/tests/InCallControllerTests.java: removes testBindToServices_classCheckFlagOn_classFound, testBindToServices_classCheckFlagOn_classNotFound, the getOptionalResolveinfo helper, and the imports that are no longer used.
- frameworks/base cbb9f1f1ab9c, core/res/AndroidManifest.xml: removes the <meta-data android:name="android.telecom.CLASS_EXISTENCE_CHECK"> element and its comment from the ConnectivityCallListenerService declaration. This is the only declarer of the metadata shown in the material. The change is cleanup: once the Telecomm change is applied, the metadata is ignored.
Completeness
- The dangerous code path is removed outright rather than gated. No branch remains in InCallController that creates a package context with CONTEXT_INCLUDE_CODE for an arbitrary InCallService package.
- The material shows only this one use of createPackageContextAsUser with CONTEXT_INCLUDE_CODE in Telecomm. It does not show whether other Telecom code paths load app code.
- The framework manifest change only removes the metadata from ConnectivityCallListenerService. The original reason for the check was builds where that class is absent, and these diffs do not replace the check with any other handling for that case.
Behavior changes
- Telecom no longer checks that an InCallService class exists before binding. A declared service whose class is missing is no longer skipped during enumeration.
- The 'android.telecom.CLASS_EXISTENCE_CHECK' metadata no longer has any effect.
- The log lines 'serviceClassExists check' and 'Skipping InCallService: class not found' are no longer emitted.
- ConnectivityCallListenerService in the framework manifest no longer declares the metadata, so the existence-check skip no longer applies to it.
Per major
- Android 14: Not affected per the bulletin. At android-security-14.0.0_r29, 4/8 lines of the patched region are present, the same count as the fixed 17 tag. This is consistent with the vulnerable check being absent (code absent).
- Android 15: Not affected per the bulletin. At android-security-15.0.0_r17, 4/8 lines are present, consistent with the vulnerable check being absent (code absent).
- Android 16: Not affected per the bulletin. At android-security-16.0.0_r8, 4/8 lines are present, consistent with the vulnerable check being absent (code absent).
- Android 17: Same fix: Telecomm 668eb07260ec and frameworks/base cbb9f1f1ab9c are in android-security-17.0.0_r1, linked by bug 501155244. The code at that tag shows the removed lines gone and the context lines retained.
Unknowns
- Which Telecom flows call getInCallServiceComponents without a package/component restriction, and therefore the exact trigger conditions.
- Whether the ignoreDisabled filtering happens before or after the removed check.
- How Telecom now handles a bound InCallService whose class is missing (bind-failure path).
- The commit message says system_server. The material does not show which process Telecom runs in on this build.
- The commit that introduced serviceClassExists / CLASS_EXISTENCE_CHECK, and whether any other branch or vendor fork carries it.