CVE-2024-34737 AI-generated analysis
platform/frameworks/base, WindowManager / ActivityTaskManager (ActivityClientController, Picture-in-Picture)
Adds a CountQuotaTracker to ActivityClientController so that an app may change the PiP aspect ratio via setPictureInPictureParams/enterPictureInPictureMode at most 60 times per minute; excess requests throw IllegalStateException.
Root cause
ActivityClientController.setPictureInPictureParams and enterPictureInPictureMode accepted PictureInPictureParams aspect ratio changes from apps without any frequency limit. Per the commit message, an app could flood PiP resizing requests this way and freeze the PiP window. Per index search, ActivityRecord.setPictureInPictureParams copies params and calls getTask().getRootTask().onPictureInPictureParamsChanged(); the material does not show the controller-to-ActivityRecord path.
How the fix works
- services/core/java/com/android/server/wm/ActivityClientController.java: adds field mSetPipAspectRatioQuotaTracker (CountQuotaTracker, @VisibleForTesting) with constants SET_PIP_ASPECT_RATIO_LIMIT = 60 and SET_PIP_ASPECT_RATIO_TIME_WINDOW_MS = 60_000 (comment notes the window cannot be smaller than QuotaTracker#MIN_WINDOW_SIZE_MS).
- ActivityClientController.ensureSetPipAspectRatioQuotaTracker(): new helper that lazily constructs the CountQuotaTracker with Categorizer.SINGLE_CATEGORIZER and sets the count limit for Category.SINGLE_CATEGORY. It is invoked before entering synchronized (mGlobalLock) because the QuotaTracker constructor uses the AM lock (deadlock avoidance, per code comment and commit message).
- ActivityClientController.enterPictureInPictureMode and ActivityClientController.setPictureInPictureParams: both call ensureSetPipAspectRatioQuotaTracker() after Binder.clearCallingIdentity() and before acquiring mGlobalLock.
- ActivityClientController.ensureValidPictureInPictureActivityParams(): after the 'activity supports PiP' check and before the min/max aspect ratio validation, if r.pictureInPictureArgs.hasSetAspectRatio() && params.hasSetAspectRatio() && the two aspect ratios differ, calls mSetPipAspectRatioQuotaTracker.noteEvent(userId, r.packageName, "setPipAspectRatio"); when noteEvent returns false it throws IllegalStateException(caller + ": Too many PiP aspect ratio change requests from " + r.packageName), aborting the request.
- services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java: testChangePipParams disables the tracker via setEnabled(false) when non-null, because the quota check causes an NPE in the test setup.
Completeness
- Covers both binder entry points shown calling ensureValidPictureInPictureActivityParams: enterPictureInPictureMode and setPictureInPictureParams.
- Only aspect ratio changes are counted; requests that change other PictureInPictureParams fields are not counted by the quota.
- The first aspect ratio set (when r.pictureInPictureArgs has no aspect ratio yet) and repeated requests with an identical aspect ratio are not counted.
- Lazy initialization of mSetPipAspectRatioQuotaTracker is an unsynchronized null check on a plain field; concurrent first calls may construct two trackers.
- Other paths that supply PictureInPictureParams (e.g. launch-into-PiP via ActivityOptions.makeLaunchIntoPip seen in ApiDemos per index search) are not shown in the material to pass through this check.
Behavior changes
- An app that changes the PiP aspect ratio more than 60 times within a 60 second window now gets an IllegalStateException from setPictureInPictureParams / enterPictureInPictureMode, where previously the request was accepted.
- A CountQuotaTracker instance is created on the first enterPictureInPictureMode/setPictureInPictureParams call, outside the WM lock.
- Legitimate apps changing aspect ratio more than 60 times per minute will hit the limit.
Per major
- Android 14: Same fix: commit 8b473b3f7964 (cherry-picked from 8d814cc3b2fc, Change-Id Icb7dd17bbf7df573a9bb28f3dc56e90e78384f4f) in android-security-14.0.0_r11; at android-security-14.0.0_r29 the patched region is fully present (8/8 lines).
- Android 15: Not affected (not listed by the bulletin); the patched region is present at android-security-15.0.0_r17 (8/8 lines).
- Android 16: Not affected (not listed by the bulletin); 7/8 lines of the patched region present at android-security-16.0.0_r8.
- Android 17: Not affected (not listed by the bulletin); 7/8 lines of the patched region present at android-security-17.0.0_r1.
Unknowns
- Fix commits for Android 12, 12L and 13 are not in the material.
- Whether ensureValidPictureInPictureActivityParams has callers other than the two shown entry points is not shown.
- Which user ID UserHandle.getCallingUserId() yields there, since it runs after Binder.clearCallingIdentity(), and therefore how the quota is keyed across users, is not shown.
- The controller code after validation (how params reach ActivityRecord and the PiP organizer) and the exact resize/freeze mechanism are not shown beyond the commit message.
- Which line of the patched region differs in Android 16 and 17 is not shown.