diff options
-rw-r--r-- | services/core/java/com/android/server/wm/ActivityClientController.java | 39 | ||||
-rw-r--r-- | services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java | 6 |
2 files changed, 45 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java index aafff2c70b8b..f2567561ed8c 100644 --- a/services/core/java/com/android/server/wm/ActivityClientController.java +++ b/services/core/java/com/android/server/wm/ActivityClientController.java @@ -96,6 +96,7 @@ import android.view.RemoteAnimationDefinition; import android.window.SizeConfigurationBuckets; import android.window.TransitionInfo; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.AssistUtils; import com.android.internal.policy.IKeyguardDismissCallback; import com.android.internal.protolog.common.ProtoLog; @@ -104,6 +105,9 @@ import com.android.server.Watchdog; import com.android.server.pm.KnownPackages; import com.android.server.pm.pkg.AndroidPackage; import com.android.server.uri.NeededUriGrants; +import com.android.server.utils.quota.Categorizer; +import com.android.server.utils.quota.Category; +import com.android.server.utils.quota.CountQuotaTracker; import com.android.server.vr.VrManagerInternal; /** @@ -119,6 +123,13 @@ class ActivityClientController extends IActivityClientController.Stub { private final ActivityTaskSupervisor mTaskSupervisor; private final Context mContext; + // Prevent malicious app abusing the Activity#setPictureInPictureParams API + @VisibleForTesting CountQuotaTracker mSetPipAspectRatioQuotaTracker; + // Limit to 60 times / minute + private static final int SET_PIP_ASPECT_RATIO_LIMIT = 60; + // The timeWindowMs here can not be smaller than QuotaTracker#MIN_WINDOW_SIZE_MS + private static final long SET_PIP_ASPECT_RATIO_TIME_WINDOW_MS = 60_000; + /** Wrapper around VoiceInteractionServiceManager. */ private AssistUtils mAssistUtils; @@ -869,6 +880,7 @@ class ActivityClientController extends IActivityClientController.Stub { public boolean enterPictureInPictureMode(IBinder token, final PictureInPictureParams params) { final long origId = Binder.clearCallingIdentity(); try { + ensureSetPipAspectRatioQuotaTracker(); synchronized (mGlobalLock) { final ActivityRecord r = ensureValidPictureInPictureActivityParams( "enterPictureInPictureMode", token, params); @@ -883,6 +895,7 @@ class ActivityClientController extends IActivityClientController.Stub { public void setPictureInPictureParams(IBinder token, final PictureInPictureParams params) { final long origId = Binder.clearCallingIdentity(); try { + ensureSetPipAspectRatioQuotaTracker(); synchronized (mGlobalLock) { final ActivityRecord r = ensureValidPictureInPictureActivityParams( "setPictureInPictureParams", token, params); @@ -935,6 +948,19 @@ class ActivityClientController extends IActivityClientController.Stub { } /** + * Initialize the {@link #mSetPipAspectRatioQuotaTracker} if applicable, which should happen + * out of {@link #mGlobalLock} to avoid deadlock (AM lock is used in QuotaTrack ctor). + */ + private void ensureSetPipAspectRatioQuotaTracker() { + if (mSetPipAspectRatioQuotaTracker == null) { + mSetPipAspectRatioQuotaTracker = new CountQuotaTracker(mContext, + Categorizer.SINGLE_CATEGORIZER); + mSetPipAspectRatioQuotaTracker.setCountLimit(Category.SINGLE_CATEGORY, + SET_PIP_ASPECT_RATIO_LIMIT, SET_PIP_ASPECT_RATIO_TIME_WINDOW_MS); + } + } + + /** * Checks the state of the system and the activity associated with the given {@param token} to * verify that picture-in-picture is supported for that activity. * @@ -958,6 +984,19 @@ class ActivityClientController extends IActivityClientController.Stub { + ": Current activity does not support picture-in-picture."); } + // Rate limit how frequent an app can request aspect ratio change via + // Activity#setPictureInPictureParams + final int userId = UserHandle.getCallingUserId(); + if (r.pictureInPictureArgs.hasSetAspectRatio() + && params.hasSetAspectRatio() + && !r.pictureInPictureArgs.getAspectRatio().equals( + params.getAspectRatio()) + && !mSetPipAspectRatioQuotaTracker.noteEvent( + userId, r.packageName, "setPipAspectRatio")) { + throw new IllegalStateException(caller + + ": Too many PiP aspect ratio change requests from " + r.packageName); + } + final float minAspectRatio = mContext.getResources().getFloat( com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio); final float maxAspectRatio = mContext.getResources().getFloat( diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java index 600681fb332c..92135e4a0206 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java @@ -1104,6 +1104,12 @@ public class WindowOrganizerTests extends WindowTestsBase { assertNotNull(o.mInfo); assertNotNull(o.mInfo.pictureInPictureParams); + // Bypass the quota check, which causes NPE in current test setup. + if (mWm.mAtmService.mActivityClientController.mSetPipAspectRatioQuotaTracker != null) { + mWm.mAtmService.mActivityClientController.mSetPipAspectRatioQuotaTracker + .setEnabled(false); + } + final PictureInPictureParams p2 = new PictureInPictureParams.Builder() .setAspectRatio(new Rational(3, 4)).build(); mWm.mAtmService.mActivityClientController.setPictureInPictureParams(record.token, p2); |