1 /* 2 * Copyright (C) 2018 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.view; 18 19 import android.annotation.IntDef; 20 import android.annotation.Nullable; 21 import android.view.InsetsState.InternalInsetType; 22 import android.view.SurfaceControl.Transaction; 23 24 import com.android.internal.annotations.VisibleForTesting; 25 26 import java.lang.annotation.Retention; 27 import java.lang.annotation.RetentionPolicy; 28 import java.util.function.Supplier; 29 30 /** 31 * Controls the visibility and animations of a single window insets source. 32 * @hide 33 */ 34 public class InsetsSourceConsumer { 35 36 @Retention(RetentionPolicy.SOURCE) 37 @IntDef(value = {ShowResult.SHOW_IMMEDIATELY, ShowResult.SHOW_DELAYED, ShowResult.SHOW_FAILED}) 38 @interface ShowResult { 39 /** 40 * Window type is ready to be shown, will be shown immidiately. 41 */ 42 int SHOW_IMMEDIATELY = 0; 43 /** 44 * Result will be delayed. Window needs to be prepared or request is not from controller. 45 * Request will be delegated to controller and may or may not be shown. 46 */ 47 int SHOW_DELAYED = 1; 48 /** 49 * Window will not be shown because one of the conditions couldn't be met. 50 * (e.g. in IME's case, when no editor is focused.) 51 */ 52 int SHOW_FAILED = 2; 53 } 54 55 protected final InsetsController mController; 56 protected boolean mVisible; 57 private final Supplier<Transaction> mTransactionSupplier; 58 private final @InternalInsetType int mType; 59 private final InsetsState mState; 60 private @Nullable InsetsSourceControl mSourceControl; 61 InsetsSourceConsumer(@nternalInsetType int type, InsetsState state, Supplier<Transaction> transactionSupplier, InsetsController controller)62 public InsetsSourceConsumer(@InternalInsetType int type, InsetsState state, 63 Supplier<Transaction> transactionSupplier, InsetsController controller) { 64 mType = type; 65 mState = state; 66 mTransactionSupplier = transactionSupplier; 67 mController = controller; 68 mVisible = InsetsState.getDefaultVisibility(type); 69 } 70 setControl(@ullable InsetsSourceControl control)71 public void setControl(@Nullable InsetsSourceControl control) { 72 if (mSourceControl == control) { 73 return; 74 } 75 mSourceControl = control; 76 applyHiddenToControl(); 77 if (applyLocalVisibilityOverride()) { 78 mController.notifyVisibilityChanged(); 79 } 80 if (mSourceControl == null) { 81 mController.notifyControlRevoked(this); 82 } 83 } 84 85 @VisibleForTesting getControl()86 public InsetsSourceControl getControl() { 87 return mSourceControl; 88 } 89 getType()90 int getType() { 91 return mType; 92 } 93 94 @VisibleForTesting show()95 public void show() { 96 setVisible(true); 97 } 98 99 @VisibleForTesting hide()100 public void hide() { 101 setVisible(false); 102 } 103 104 /** 105 * Called when current window gains focus 106 */ onWindowFocusGained()107 public void onWindowFocusGained() {} 108 109 /** 110 * Called when current window loses focus. 111 */ onWindowFocusLost()112 public void onWindowFocusLost() {} 113 applyLocalVisibilityOverride()114 boolean applyLocalVisibilityOverride() { 115 116 // If we don't have control, we are not able to change the visibility. 117 if (mSourceControl == null) { 118 return false; 119 } 120 if (mState.getSource(mType).isVisible() == mVisible) { 121 return false; 122 } 123 mState.getSource(mType).setVisible(mVisible); 124 return true; 125 } 126 127 @VisibleForTesting isVisible()128 public boolean isVisible() { 129 return mVisible; 130 } 131 132 /** 133 * Request to show current window type. 134 * 135 * @param fromController {@code true} if request is coming from controller. 136 * (e.g. in IME case, controller is 137 * {@link android.inputmethodservice.InputMethodService}). 138 * @return @see {@link ShowResult}. 139 */ requestShow(boolean fromController)140 @ShowResult int requestShow(boolean fromController) { 141 return ShowResult.SHOW_IMMEDIATELY; 142 } 143 144 /** 145 * Notify listeners that window is now hidden. 146 */ notifyHidden()147 void notifyHidden() { 148 // no-op for types that always return ShowResult#SHOW_IMMEDIATELY. 149 } 150 setVisible(boolean visible)151 private void setVisible(boolean visible) { 152 if (mVisible == visible) { 153 return; 154 } 155 mVisible = visible; 156 applyHiddenToControl(); 157 applyLocalVisibilityOverride(); 158 mController.notifyVisibilityChanged(); 159 } 160 applyHiddenToControl()161 private void applyHiddenToControl() { 162 if (mSourceControl == null) { 163 return; 164 } 165 166 final Transaction t = mTransactionSupplier.get(); 167 if (mVisible) { 168 t.show(mSourceControl.getLeash()); 169 } else { 170 t.hide(mSourceControl.getLeash()); 171 } 172 t.apply(); 173 } 174 } 175