summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/current.txt1
-rw-r--r--core/java/android/app/Activity.java22
-rw-r--r--core/java/android/app/multitasking.aconfig8
-rw-r--r--core/res/Android.bp1
-rw-r--r--core/res/AndroidManifest.xml12
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java16
6 files changed, 60 insertions, 0 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index eb4973999e25..63aca2600a31 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -314,6 +314,7 @@ package android {
field public static final String SYSTEM_ALERT_WINDOW = "android.permission.SYSTEM_ALERT_WINDOW";
field public static final String TRANSMIT_IR = "android.permission.TRANSMIT_IR";
field public static final String TURN_SCREEN_ON = "android.permission.TURN_SCREEN_ON";
+ field @FlaggedApi("android.app.enable_tv_implicit_enter_pip_restriction") public static final String TV_IMPLICIT_ENTER_PIP = "android.permission.TV_IMPLICIT_ENTER_PIP";
field public static final String UNINSTALL_SHORTCUT = "com.android.launcher.permission.UNINSTALL_SHORTCUT";
field public static final String UPDATE_DEVICE_STATS = "android.permission.UPDATE_DEVICE_STATS";
field public static final String UPDATE_PACKAGES_WITHOUT_USER_ACTION = "android.permission.UPDATE_PACKAGES_WITHOUT_USER_ACTION";
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 7a1c759a3ec4..3fccc17e1bf1 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -30,6 +30,7 @@ import static com.android.sdksandbox.flags.Flags.sandboxActivitySdkBasedContext;
import static java.lang.Character.MIN_VALUE;
+import android.Manifest;
import android.annotation.AnimRes;
import android.annotation.CallSuper;
import android.annotation.CallbackExecutor;
@@ -3193,6 +3194,16 @@ public class Activity extends ContextThemeWrapper
return ActivityTaskManager.getMaxNumPictureInPictureActions(this);
}
+ private boolean isImplicitEnterPipProhibited() {
+ PackageManager pm = getPackageManager();
+ if (android.app.Flags.enableTvImplicitEnterPipRestriction()) {
+ return pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
+ && pm.checkPermission(Manifest.permission.TV_IMPLICIT_ENTER_PIP,
+ getPackageName()) == PackageManager.PERMISSION_DENIED;
+ }
+ return false;
+ }
+
/**
* @return Whether this device supports picture-in-picture.
*/
@@ -9192,6 +9203,8 @@ public class Activity extends ContextThemeWrapper
}
dispatchActivityPreResumed();
+ mCanEnterPictureInPicture = true;
+
mFragments.execPendingActions();
mLastNonConfigurationInstances = null;
@@ -9243,6 +9256,11 @@ public class Activity extends ContextThemeWrapper
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "performPause:"
+ mComponent.getClassName());
}
+
+ if (isImplicitEnterPipProhibited()) {
+ mCanEnterPictureInPicture = false;
+ }
+
dispatchActivityPrePaused();
mDoReportFullyDrawn = false;
mFragments.dispatchPause();
@@ -9265,6 +9283,10 @@ public class Activity extends ContextThemeWrapper
final void performUserLeaving() {
onUserInteraction();
+
+ if (isImplicitEnterPipProhibited()) {
+ mCanEnterPictureInPicture = false;
+ }
onUserLeaveHint();
}
diff --git a/core/java/android/app/multitasking.aconfig b/core/java/android/app/multitasking.aconfig
index 9a645192a155..c8455c1f439f 100644
--- a/core/java/android/app/multitasking.aconfig
+++ b/core/java/android/app/multitasking.aconfig
@@ -8,3 +8,11 @@ flag {
description: "Enables PiP UI state callback on entering"
bug: "303718131"
}
+
+flag {
+ name: "enable_tv_implicit_enter_pip_restriction"
+ is_exported: true
+ namespace: "tv_system_ui"
+ description: "Enables restrictions to PiP entry on TV for setAutoEnterEnabled and lifecycle methods"
+ bug: "283115999"
+}
diff --git a/core/res/Android.bp b/core/res/Android.bp
index c66d2b57fcef..73776f0d0b1d 100644
--- a/core/res/Android.bp
+++ b/core/res/Android.bp
@@ -158,6 +158,7 @@ android_app {
flags_packages: [
"android.app.appfunctions.flags-aconfig",
"android.app.contextualsearch.flags-aconfig",
+ "android.app.flags-aconfig",
"android.appwidget.flags-aconfig",
"android.content.pm.flags-aconfig",
"android.provider.flags-aconfig",
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 44bda1c8a877..0e4eb94feffb 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4463,6 +4463,18 @@
android:description="@string/permdesc_hideOverlayWindows"
android:protectionLevel="normal" />
+ <!-- Allows an app to enter Picture-in-Picture mode when the user is not explicitly requesting
+ it. This includes using {@link PictureInPictureParams.Builder#setAutoEnterEnabled} as well
+ as lifecycle methods such as {@link Activity#onUserLeaveHint} and {@link Activity#onPause}
+ to enter PiP when the user leaves the app.
+ This permission should only be used for certain PiP
+ <a href="{@docRoot}training/tv/get-started/multitasking#usage-types">usage types</a>.
+ @FlaggedApi(android.app.Flags.FLAG_ENABLE_TV_IMPLICIT_ENTER_PIP_RESTRICTION)
+ -->
+ <permission android:name="android.permission.TV_IMPLICIT_ENTER_PIP"
+ android:protectionLevel="normal"
+ android:featureFlag="android.app.enable_tv_implicit_enter_pip_restriction" />
+
<!-- ================================== -->
<!-- Permissions affecting the system wallpaper -->
<!-- ================================== -->
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 73ae51c6e64a..14be59f27f84 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -254,6 +254,7 @@ import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.END_TAG;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
+import android.Manifest;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -10308,6 +10309,21 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (pictureInPictureArgs != null && pictureInPictureArgs.hasSourceBoundsHint()) {
pictureInPictureArgs.getSourceRectHint().offset(windowBounds.left, windowBounds.top);
}
+
+ if (android.app.Flags.enableTvImplicitEnterPipRestriction()) {
+ PackageManager pm = mAtmService.mContext.getPackageManager();
+ if (pictureInPictureArgs.isAutoEnterEnabled()
+ && pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
+ && pm.checkPermission(Manifest.permission.TV_IMPLICIT_ENTER_PIP, packageName)
+ == PackageManager.PERMISSION_DENIED) {
+ Log.i(TAG,
+ "Auto-enter PiP only allowed on TV if android.permission"
+ + ".TV_IMPLICIT_ENTER_PIP permission is held by the app.");
+ PictureInPictureParams.Builder builder = new PictureInPictureParams.Builder();
+ builder.setAutoEnterEnabled(false);
+ pictureInPictureArgs.copyOnlySet(builder.build());
+ }
+ }
}
private void applyLocaleOverrideIfNeeded(Configuration resolvedConfig) {