1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.app; 18 19 import static android.app.Activity.FULLSCREEN_MODE_REQUEST_ENTER; 20 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; 21 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; 22 23 import android.annotation.IntDef; 24 import android.annotation.NonNull; 25 import android.annotation.Nullable; 26 import android.content.res.Configuration; 27 import android.os.Bundle; 28 import android.os.IBinder; 29 import android.os.IRemoteCallback; 30 import android.os.OutcomeReceiver; 31 32 /** 33 * @hide 34 */ 35 public class FullscreenRequestHandler { 36 @IntDef(prefix = { "RESULT_" }, value = { 37 RESULT_APPROVED, 38 RESULT_FAILED_NOT_IN_FREEFORM, 39 RESULT_FAILED_NOT_IN_FULLSCREEN_WITH_HISTORY, 40 RESULT_FAILED_NOT_DEFAULT_FREEFORM, 41 RESULT_FAILED_NOT_TOP_FOCUSED 42 }) 43 public @interface RequestResult {} 44 45 public static final int RESULT_APPROVED = 0; 46 public static final int RESULT_FAILED_NOT_IN_FREEFORM = 1; 47 public static final int RESULT_FAILED_NOT_IN_FULLSCREEN_WITH_HISTORY = 2; 48 public static final int RESULT_FAILED_NOT_DEFAULT_FREEFORM = 3; 49 public static final int RESULT_FAILED_NOT_TOP_FOCUSED = 4; 50 51 public static final String REMOTE_CALLBACK_RESULT_KEY = "result"; 52 requestFullscreenMode(@onNull @ctivity.FullscreenModeRequest int request, @Nullable OutcomeReceiver<Void, Throwable> approvalCallback, Configuration config, IBinder token)53 static void requestFullscreenMode(@NonNull @Activity.FullscreenModeRequest int request, 54 @Nullable OutcomeReceiver<Void, Throwable> approvalCallback, Configuration config, 55 IBinder token) { 56 int earlyCheck = earlyCheckRequestMatchesWindowingMode( 57 request, config.windowConfiguration.getWindowingMode()); 58 if (earlyCheck != RESULT_APPROVED) { 59 if (approvalCallback != null) { 60 notifyFullscreenRequestResult(approvalCallback, earlyCheck); 61 } 62 return; 63 } 64 try { 65 if (approvalCallback != null) { 66 ActivityClient.getInstance().requestMultiwindowFullscreen(token, request, 67 new IRemoteCallback.Stub() { 68 @Override 69 public void sendResult(Bundle res) { 70 notifyFullscreenRequestResult( 71 approvalCallback, res.getInt(REMOTE_CALLBACK_RESULT_KEY)); 72 } 73 }); 74 } else { 75 ActivityClient.getInstance().requestMultiwindowFullscreen(token, request, null); 76 } 77 } catch (Throwable e) { 78 if (approvalCallback != null) { 79 approvalCallback.onError(e); 80 } 81 } 82 } 83 notifyFullscreenRequestResult( OutcomeReceiver<Void, Throwable> callback, int result)84 private static void notifyFullscreenRequestResult( 85 OutcomeReceiver<Void, Throwable> callback, int result) { 86 Throwable e = null; 87 switch (result) { 88 case RESULT_FAILED_NOT_IN_FREEFORM: 89 e = new IllegalStateException("The window is not a freeform window, the request " 90 + "to get into fullscreen cannot be approved."); 91 break; 92 case RESULT_FAILED_NOT_IN_FULLSCREEN_WITH_HISTORY: 93 e = new IllegalStateException("The window is not in fullscreen by calling the " 94 + "requestFullscreenMode API before, such that cannot be restored."); 95 break; 96 case RESULT_FAILED_NOT_DEFAULT_FREEFORM: 97 e = new IllegalStateException("The window is not launched in freeform by default."); 98 break; 99 case RESULT_FAILED_NOT_TOP_FOCUSED: 100 e = new IllegalStateException("The window is not the top focused window."); 101 break; 102 default: 103 callback.onResult(null); 104 break; 105 } 106 if (e != null) { 107 callback.onError(e); 108 } 109 } 110 earlyCheckRequestMatchesWindowingMode(int request, int windowingMode)111 private static int earlyCheckRequestMatchesWindowingMode(int request, int windowingMode) { 112 if (request == FULLSCREEN_MODE_REQUEST_ENTER) { 113 if (windowingMode != WINDOWING_MODE_FREEFORM) { 114 return RESULT_FAILED_NOT_IN_FREEFORM; 115 } 116 } else { 117 if (windowingMode != WINDOWING_MODE_FULLSCREEN) { 118 return RESULT_FAILED_NOT_IN_FULLSCREEN_WITH_HISTORY; 119 } 120 } 121 return RESULT_APPROVED; 122 } 123 } 124