[MediaProjection] Clarify createVirtualDisplay exception javadoc
The SecurityException has been present for several releases, but
undocumented until earlier in Android U development.
Ensure that token re-use throws SecurityException, and only
a missing callback results in IllegalStateException.
Clarify that the SecurityException is only thrown when an app
invokes MediaProjection#stop before attempting to capture again.
Since an app does not have to invoke that method to end a
recording (for example, they may stop the MediaRecorder instance
only), the IllegalStateException is thrown in this scenario.
Bug: 286252090
Test: atest FrameworksServicesTests:MediaProjectionManagerServiceTest
Change-Id: I2c6f151e806430330a76482d7c6e3c89adfc19a0
diff --git a/media/java/android/media/projection/MediaProjection.java b/media/java/android/media/projection/MediaProjection.java
index 48367f9..fb72c7b 100644
--- a/media/java/android/media/projection/MediaProjection.java
+++ b/media/java/android/media/projection/MediaProjection.java
@@ -171,25 +171,30 @@
* @param handler The {@link android.os.Handler} on which the callback should be invoked, or
* null if the callback should be invoked on the calling thread's main
* {@link android.os.Looper}.
- * @throws IllegalStateException In the following scenarios, if the target SDK is {@link
- * android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE U} and up:
+ * @throws IllegalStateException If the target SDK is {@link
+ * android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE U} and up, and
+ * if no {@link Callback} is registered.
+ * @throws SecurityException In any of the following scenarios:
* <ol>
- * <li>If no {@link Callback} is registered.</li>
- * <li>If {@link MediaProjectionManager#getMediaProjection}
+ * <li>If attempting to create a new virtual display
+ * associated with this MediaProjection instance after it has
+ * been stopped by invoking {@link #stop()}.
+ * <li>If the target SDK is {@link
+ * android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE U} and up,
+ * and if this instance has already taken a recording through
+ * {@code #createVirtualDisplay}, but {@link #stop()} wasn't
+ * invoked to end the recording.
+ * <li>If the target SDK is {@link
+ * android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE U} and up,
+ * and if {@link MediaProjectionManager#getMediaProjection}
* was invoked more than once to get this
* {@code MediaProjection} instance.
- * <li>If this instance has already taken a recording through
- * {@code #createVirtualDisplay}.
* </ol>
- * However, if the target SDK is less than
- * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE U}, no
- * exception is thrown. In case 1, recording begins even without
- * the callback. In case 2 & 3, recording doesn't begin
- * until the user re-grants consent in the dialog.
- * @throws SecurityException If attempting to create a new virtual display associated with this
- * MediaProjection instance after it has been stopped by invoking
- * {@link #stop()}.
- *
+ * In cases 2 & 3, no exception is thrown if the target SDK is
+ * less than
+ * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE U}.
+ * Instead, recording doesn't begin until the user re-grants
+ * consent in the dialog.
* @see VirtualDisplay
* @see VirtualDisplay.Callback
*/
diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
index 5324acd..65e34e6 100644
--- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
+++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
@@ -1078,7 +1078,7 @@
// Tear down projection here; necessary to ensure (among other reasons) that
// stop is dispatched to client and cast icon disappears from status bar.
mProjectionGrant.stop();
- throw new IllegalStateException("Don't re-use the resultData to retrieve "
+ throw new SecurityException("Don't re-use the resultData to retrieve "
+ "the same projection instance, and don't use a token that has "
+ "timed out. Don't take multiple captures by invoking "
+ "MediaProjection#createVirtualDisplay multiple times on the "
diff --git a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java
index b91a6cb..c42928e 100644
--- a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java
@@ -344,7 +344,7 @@
// Second start - so not valid.
projection.start(mIMediaProjectionCallback);
- assertThrows(IllegalStateException.class, projection::isValid);
+ assertThrows(SecurityException.class, projection::isValid);
}
// TODO(269273190): Test flag using compat annotations instead.