Loading core/api/current.txt +3 −0 Original line number Diff line number Diff line Loading @@ -4292,6 +4292,7 @@ package android.app { method @Deprecated public final void removeDialog(int); method public void reportFullyDrawn(); method public android.view.DragAndDropPermissions requestDragAndDropPermissions(android.view.DragEvent); method public void requestFullscreenMode(@NonNull int, @Nullable android.os.OutcomeReceiver<java.lang.Void,java.lang.Throwable>); method public final void requestPermissions(@NonNull String[], int); method public final void requestShowKeyboardShortcuts(); method @Deprecated public boolean requestVisibleBehind(boolean); Loading Loading @@ -4378,6 +4379,8 @@ package android.app { field public static final int DEFAULT_KEYS_SEARCH_LOCAL = 3; // 0x3 field public static final int DEFAULT_KEYS_SHORTCUT = 2; // 0x2 field protected static final int[] FOCUSED_STATE_SET; field public static final int FULLSCREEN_MODE_REQUEST_ENTER = 1; // 0x1 field public static final int FULLSCREEN_MODE_REQUEST_EXIT = 0; // 0x0 field public static final int RESULT_CANCELED = 0; // 0x0 field public static final int RESULT_FIRST_USER = 1; // 0x1 field public static final int RESULT_OK = -1; // 0xffffffff core/java/android/app/Activity.java +42 −0 Original line number Diff line number Diff line Loading @@ -83,6 +83,7 @@ import android.os.GraphicsEnvironment; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.OutcomeReceiver; import android.os.Parcelable; import android.os.PersistableBundle; import android.os.Process; Loading Loading @@ -987,6 +988,17 @@ public class Activity extends ContextThemeWrapper /** @hide */ boolean mIsInPictureInPictureMode; /** @hide */ @IntDef(prefix = { "FULLSCREEN_REQUEST_" }, value = { FULLSCREEN_MODE_REQUEST_EXIT, FULLSCREEN_MODE_REQUEST_ENTER }) public @interface FullscreenModeRequest {} public static final int FULLSCREEN_MODE_REQUEST_EXIT = 0; public static final int FULLSCREEN_MODE_REQUEST_ENTER = 1; private boolean mShouldDockBigOverlays; private UiTranslationController mUiTranslationController; Loading Loading @@ -3000,6 +3012,36 @@ public class Activity extends ContextThemeWrapper return false; } /** * Request to put the a freeform activity into fullscreen. This will only be allowed if the * activity is on a freeform display, such as a desktop device. The requester has to be the * top-most activity and the request should be a response to a user input. When getting * fullscreen and receiving corresponding {@link #onConfigurationChanged(Configuration)} and * {@link #onMultiWindowModeChanged(boolean, Configuration)}, the activity should relayout * itself and the system bars' visibilities can be controlled as usual fullscreen apps. * * Calling it again with the exit request can restore the activity to the previous status. * This will only happen when it got into fullscreen through this API. * * If an app wants to be in fullscreen always, it should claim as not being resizable * by setting * <a href="https://developer.android.com/guide/topics/large-screens/multi-window-support#resizeableActivity"> * {@code android:resizableActivity="false"}</a> instead of calling this API. * * @param request Can be {@link #FULLSCREEN_MODE_REQUEST_ENTER} or * {@link #FULLSCREEN_MODE_REQUEST_EXIT} to indicate this request is to get * fullscreen or get restored. * @param approvalCallback Optional callback, use {@code null} when not necessary. When the * request is approved or rejected, the callback will be triggered. This * will happen before any configuration change. The callback will be * dispatched on the main thread. */ public void requestFullscreenMode(@NonNull @FullscreenModeRequest int request, @Nullable OutcomeReceiver<Void, Throwable> approvalCallback) { FullscreenRequestHandler.requestFullscreenMode( request, approvalCallback, mCurrentConfig, getActivityToken()); } /** * Specifies a preference to dock big overlays like the expanded picture-in-picture on TV * (see {@link PictureInPictureParams.Builder#setExpandedAspectRatio}). Docking puts the Loading core/java/android/app/ActivityClient.java +9 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.os.Bundle; import android.os.IBinder; import android.os.IRemoteCallback; import android.os.PersistableBundle; import android.os.RemoteException; import android.util.Singleton; Loading Loading @@ -372,6 +373,14 @@ public class ActivityClient { } } void requestMultiwindowFullscreen(IBinder token, int request, IRemoteCallback callback) { try { getActivityClientController().requestMultiwindowFullscreen(token, request, callback); } catch (RemoteException e) { e.rethrowFromSystemServer(); } } void startLockTaskModeByToken(IBinder token) { try { getActivityClientController().startLockTaskModeByToken(token); Loading core/java/android/app/ActivityTaskManager.java +6 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,12 @@ public class ActivityTaskManager { */ public static final int INVALID_TASK_ID = -1; /** * Invalid windowing mode. * @hide */ public static final int INVALID_WINDOWING_MODE = -1; /** * Input parameter to {@link IActivityTaskManager#resizeTask} which indicates * that the resize doesn't need to preserve the window, and can be skipped if bounds Loading core/java/android/app/FullscreenRequestHandler.java 0 → 100644 +123 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.app; import static android.app.Activity.FULLSCREEN_MODE_REQUEST_ENTER; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.res.Configuration; import android.os.Bundle; import android.os.IBinder; import android.os.IRemoteCallback; import android.os.OutcomeReceiver; /** * @hide */ public class FullscreenRequestHandler { @IntDef(prefix = { "RESULT_" }, value = { RESULT_APPROVED, RESULT_FAILED_NOT_IN_FREEFORM, RESULT_FAILED_NOT_IN_FULLSCREEN_WITH_HISTORY, RESULT_FAILED_NOT_DEFAULT_FREEFORM, RESULT_FAILED_NOT_TOP_FOCUSED }) public @interface RequestResult {} public static final int RESULT_APPROVED = 0; public static final int RESULT_FAILED_NOT_IN_FREEFORM = 1; public static final int RESULT_FAILED_NOT_IN_FULLSCREEN_WITH_HISTORY = 2; public static final int RESULT_FAILED_NOT_DEFAULT_FREEFORM = 3; public static final int RESULT_FAILED_NOT_TOP_FOCUSED = 4; public static final String REMOTE_CALLBACK_RESULT_KEY = "result"; static void requestFullscreenMode(@NonNull @Activity.FullscreenModeRequest int request, @Nullable OutcomeReceiver<Void, Throwable> approvalCallback, Configuration config, IBinder token) { int earlyCheck = earlyCheckRequestMatchesWindowingMode( request, config.windowConfiguration.getWindowingMode()); if (earlyCheck != RESULT_APPROVED) { if (approvalCallback != null) { notifyFullscreenRequestResult(approvalCallback, earlyCheck); } return; } try { if (approvalCallback != null) { ActivityClient.getInstance().requestMultiwindowFullscreen(token, request, new IRemoteCallback.Stub() { @Override public void sendResult(Bundle res) { notifyFullscreenRequestResult( approvalCallback, res.getInt(REMOTE_CALLBACK_RESULT_KEY)); } }); } else { ActivityClient.getInstance().requestMultiwindowFullscreen(token, request, null); } } catch (Throwable e) { if (approvalCallback != null) { approvalCallback.onError(e); } } } private static void notifyFullscreenRequestResult( OutcomeReceiver<Void, Throwable> callback, int result) { Throwable e = null; switch (result) { case RESULT_FAILED_NOT_IN_FREEFORM: e = new IllegalStateException("The window is not a freeform window, the request " + "to get into fullscreen cannot be approved."); break; case RESULT_FAILED_NOT_IN_FULLSCREEN_WITH_HISTORY: e = new IllegalStateException("The window is not in fullscreen by calling the " + "requestFullscreenMode API before, such that cannot be restored."); break; case RESULT_FAILED_NOT_DEFAULT_FREEFORM: e = new IllegalStateException("The window is not launched in freeform by default."); break; case RESULT_FAILED_NOT_TOP_FOCUSED: e = new IllegalStateException("The window is not the top focused window."); break; default: callback.onResult(null); break; } if (e != null) { callback.onError(e); } } private static int earlyCheckRequestMatchesWindowingMode(int request, int windowingMode) { if (request == FULLSCREEN_MODE_REQUEST_ENTER) { if (windowingMode != WINDOWING_MODE_FREEFORM) { return RESULT_FAILED_NOT_IN_FREEFORM; } } else { if (windowingMode != WINDOWING_MODE_FULLSCREEN) { return RESULT_FAILED_NOT_IN_FULLSCREEN_WITH_HISTORY; } } return RESULT_APPROVED; } } Loading
core/api/current.txt +3 −0 Original line number Diff line number Diff line Loading @@ -4292,6 +4292,7 @@ package android.app { method @Deprecated public final void removeDialog(int); method public void reportFullyDrawn(); method public android.view.DragAndDropPermissions requestDragAndDropPermissions(android.view.DragEvent); method public void requestFullscreenMode(@NonNull int, @Nullable android.os.OutcomeReceiver<java.lang.Void,java.lang.Throwable>); method public final void requestPermissions(@NonNull String[], int); method public final void requestShowKeyboardShortcuts(); method @Deprecated public boolean requestVisibleBehind(boolean); Loading Loading @@ -4378,6 +4379,8 @@ package android.app { field public static final int DEFAULT_KEYS_SEARCH_LOCAL = 3; // 0x3 field public static final int DEFAULT_KEYS_SHORTCUT = 2; // 0x2 field protected static final int[] FOCUSED_STATE_SET; field public static final int FULLSCREEN_MODE_REQUEST_ENTER = 1; // 0x1 field public static final int FULLSCREEN_MODE_REQUEST_EXIT = 0; // 0x0 field public static final int RESULT_CANCELED = 0; // 0x0 field public static final int RESULT_FIRST_USER = 1; // 0x1 field public static final int RESULT_OK = -1; // 0xffffffff
core/java/android/app/Activity.java +42 −0 Original line number Diff line number Diff line Loading @@ -83,6 +83,7 @@ import android.os.GraphicsEnvironment; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.OutcomeReceiver; import android.os.Parcelable; import android.os.PersistableBundle; import android.os.Process; Loading Loading @@ -987,6 +988,17 @@ public class Activity extends ContextThemeWrapper /** @hide */ boolean mIsInPictureInPictureMode; /** @hide */ @IntDef(prefix = { "FULLSCREEN_REQUEST_" }, value = { FULLSCREEN_MODE_REQUEST_EXIT, FULLSCREEN_MODE_REQUEST_ENTER }) public @interface FullscreenModeRequest {} public static final int FULLSCREEN_MODE_REQUEST_EXIT = 0; public static final int FULLSCREEN_MODE_REQUEST_ENTER = 1; private boolean mShouldDockBigOverlays; private UiTranslationController mUiTranslationController; Loading Loading @@ -3000,6 +3012,36 @@ public class Activity extends ContextThemeWrapper return false; } /** * Request to put the a freeform activity into fullscreen. This will only be allowed if the * activity is on a freeform display, such as a desktop device. The requester has to be the * top-most activity and the request should be a response to a user input. When getting * fullscreen and receiving corresponding {@link #onConfigurationChanged(Configuration)} and * {@link #onMultiWindowModeChanged(boolean, Configuration)}, the activity should relayout * itself and the system bars' visibilities can be controlled as usual fullscreen apps. * * Calling it again with the exit request can restore the activity to the previous status. * This will only happen when it got into fullscreen through this API. * * If an app wants to be in fullscreen always, it should claim as not being resizable * by setting * <a href="https://developer.android.com/guide/topics/large-screens/multi-window-support#resizeableActivity"> * {@code android:resizableActivity="false"}</a> instead of calling this API. * * @param request Can be {@link #FULLSCREEN_MODE_REQUEST_ENTER} or * {@link #FULLSCREEN_MODE_REQUEST_EXIT} to indicate this request is to get * fullscreen or get restored. * @param approvalCallback Optional callback, use {@code null} when not necessary. When the * request is approved or rejected, the callback will be triggered. This * will happen before any configuration change. The callback will be * dispatched on the main thread. */ public void requestFullscreenMode(@NonNull @FullscreenModeRequest int request, @Nullable OutcomeReceiver<Void, Throwable> approvalCallback) { FullscreenRequestHandler.requestFullscreenMode( request, approvalCallback, mCurrentConfig, getActivityToken()); } /** * Specifies a preference to dock big overlays like the expanded picture-in-picture on TV * (see {@link PictureInPictureParams.Builder#setExpandedAspectRatio}). Docking puts the Loading
core/java/android/app/ActivityClient.java +9 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.os.Bundle; import android.os.IBinder; import android.os.IRemoteCallback; import android.os.PersistableBundle; import android.os.RemoteException; import android.util.Singleton; Loading Loading @@ -372,6 +373,14 @@ public class ActivityClient { } } void requestMultiwindowFullscreen(IBinder token, int request, IRemoteCallback callback) { try { getActivityClientController().requestMultiwindowFullscreen(token, request, callback); } catch (RemoteException e) { e.rethrowFromSystemServer(); } } void startLockTaskModeByToken(IBinder token) { try { getActivityClientController().startLockTaskModeByToken(token); Loading
core/java/android/app/ActivityTaskManager.java +6 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,12 @@ public class ActivityTaskManager { */ public static final int INVALID_TASK_ID = -1; /** * Invalid windowing mode. * @hide */ public static final int INVALID_WINDOWING_MODE = -1; /** * Input parameter to {@link IActivityTaskManager#resizeTask} which indicates * that the resize doesn't need to preserve the window, and can be skipped if bounds Loading
core/java/android/app/FullscreenRequestHandler.java 0 → 100644 +123 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.app; import static android.app.Activity.FULLSCREEN_MODE_REQUEST_ENTER; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.res.Configuration; import android.os.Bundle; import android.os.IBinder; import android.os.IRemoteCallback; import android.os.OutcomeReceiver; /** * @hide */ public class FullscreenRequestHandler { @IntDef(prefix = { "RESULT_" }, value = { RESULT_APPROVED, RESULT_FAILED_NOT_IN_FREEFORM, RESULT_FAILED_NOT_IN_FULLSCREEN_WITH_HISTORY, RESULT_FAILED_NOT_DEFAULT_FREEFORM, RESULT_FAILED_NOT_TOP_FOCUSED }) public @interface RequestResult {} public static final int RESULT_APPROVED = 0; public static final int RESULT_FAILED_NOT_IN_FREEFORM = 1; public static final int RESULT_FAILED_NOT_IN_FULLSCREEN_WITH_HISTORY = 2; public static final int RESULT_FAILED_NOT_DEFAULT_FREEFORM = 3; public static final int RESULT_FAILED_NOT_TOP_FOCUSED = 4; public static final String REMOTE_CALLBACK_RESULT_KEY = "result"; static void requestFullscreenMode(@NonNull @Activity.FullscreenModeRequest int request, @Nullable OutcomeReceiver<Void, Throwable> approvalCallback, Configuration config, IBinder token) { int earlyCheck = earlyCheckRequestMatchesWindowingMode( request, config.windowConfiguration.getWindowingMode()); if (earlyCheck != RESULT_APPROVED) { if (approvalCallback != null) { notifyFullscreenRequestResult(approvalCallback, earlyCheck); } return; } try { if (approvalCallback != null) { ActivityClient.getInstance().requestMultiwindowFullscreen(token, request, new IRemoteCallback.Stub() { @Override public void sendResult(Bundle res) { notifyFullscreenRequestResult( approvalCallback, res.getInt(REMOTE_CALLBACK_RESULT_KEY)); } }); } else { ActivityClient.getInstance().requestMultiwindowFullscreen(token, request, null); } } catch (Throwable e) { if (approvalCallback != null) { approvalCallback.onError(e); } } } private static void notifyFullscreenRequestResult( OutcomeReceiver<Void, Throwable> callback, int result) { Throwable e = null; switch (result) { case RESULT_FAILED_NOT_IN_FREEFORM: e = new IllegalStateException("The window is not a freeform window, the request " + "to get into fullscreen cannot be approved."); break; case RESULT_FAILED_NOT_IN_FULLSCREEN_WITH_HISTORY: e = new IllegalStateException("The window is not in fullscreen by calling the " + "requestFullscreenMode API before, such that cannot be restored."); break; case RESULT_FAILED_NOT_DEFAULT_FREEFORM: e = new IllegalStateException("The window is not launched in freeform by default."); break; case RESULT_FAILED_NOT_TOP_FOCUSED: e = new IllegalStateException("The window is not the top focused window."); break; default: callback.onResult(null); break; } if (e != null) { callback.onError(e); } } private static int earlyCheckRequestMatchesWindowingMode(int request, int windowingMode) { if (request == FULLSCREEN_MODE_REQUEST_ENTER) { if (windowingMode != WINDOWING_MODE_FREEFORM) { return RESULT_FAILED_NOT_IN_FREEFORM; } } else { if (windowingMode != WINDOWING_MODE_FULLSCREEN) { return RESULT_FAILED_NOT_IN_FULLSCREEN_WITH_HISTORY; } } return RESULT_APPROVED; } }