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 com.android.server.wm; 18 19 import static android.view.InsetsState.TYPE_IME; 20 import static android.view.InsetsState.TYPE_NAVIGATION_BAR; 21 import static android.view.InsetsState.TYPE_TOP_BAR; 22 import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL; 23 import static android.view.ViewRootImpl.NEW_INSETS_MODE_IME; 24 import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE; 25 import static android.view.ViewRootImpl.sNewInsetsMode; 26 27 import android.annotation.NonNull; 28 import android.annotation.Nullable; 29 import android.graphics.Point; 30 import android.graphics.Rect; 31 import android.util.proto.ProtoOutputStream; 32 import android.view.InsetsSource; 33 import android.view.InsetsSourceControl; 34 import android.view.InsetsState; 35 import android.view.SurfaceControl; 36 import android.view.SurfaceControl.Transaction; 37 38 import com.android.internal.util.function.TriConsumer; 39 import com.android.internal.util.function.pooled.PooledLambda; 40 import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback; 41 42 import java.io.PrintWriter; 43 44 /** 45 * Controller for a specific inset source on the server. It's called provider as it provides the 46 * {@link InsetsSource} to the client that uses it in {@link InsetsSourceConsumer}. 47 */ 48 class InsetsSourceProvider { 49 50 private final Rect mTmpRect = new Rect(); 51 private final @NonNull InsetsSource mSource; 52 private final DisplayContent mDisplayContent; 53 private final InsetsStateController mStateController; 54 private @Nullable InsetsSourceControl mControl; 55 private @Nullable WindowState mControllingWin; 56 private @Nullable ControlAdapter mAdapter; 57 private WindowState mWin; 58 private TriConsumer<DisplayFrames, WindowState, Rect> mFrameProvider; 59 60 /** The visibility override from the current controlling window. */ 61 private boolean mClientVisible; 62 63 /** 64 * Whether the window is available and considered visible as in {@link WindowState#isVisible}. 65 */ 66 private boolean mServerVisible; 67 68 private final boolean mControllable; 69 InsetsSourceProvider(InsetsSource source, InsetsStateController stateController, DisplayContent displayContent)70 InsetsSourceProvider(InsetsSource source, InsetsStateController stateController, 71 DisplayContent displayContent) { 72 mClientVisible = InsetsState.getDefaultVisibility(source.getType()); 73 mSource = source; 74 mDisplayContent = displayContent; 75 mStateController = stateController; 76 77 final int type = source.getType(); 78 if (type == TYPE_TOP_BAR || type == TYPE_NAVIGATION_BAR) { 79 mControllable = sNewInsetsMode == NEW_INSETS_MODE_FULL; 80 } else if (type == TYPE_IME) { 81 mControllable = sNewInsetsMode >= NEW_INSETS_MODE_IME; 82 } else { 83 mControllable = false; 84 } 85 } 86 getSource()87 InsetsSource getSource() { 88 return mSource; 89 } 90 91 /** 92 * @return Whether the current flag configuration allows to control this source. 93 */ isControllable()94 boolean isControllable() { 95 return mControllable; 96 } 97 98 /** 99 * Updates the window that currently backs this source. 100 * 101 * @param win The window that links to this source. 102 * @param frameProvider Based on display frame state and the window, calculates the resulting 103 * frame that should be reported to clients. 104 */ setWindow(@ullable WindowState win, @Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider)105 void setWindow(@Nullable WindowState win, 106 @Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider) { 107 if (mWin != null) { 108 mWin.setInsetProvider(null); 109 } 110 mWin = win; 111 mFrameProvider = frameProvider; 112 if (win == null) { 113 setServerVisible(false); 114 mSource.setFrame(new Rect()); 115 } else { 116 mWin.setInsetProvider(this); 117 if (mControllingWin != null) { 118 updateControlForTarget(mControllingWin, true /* force */); 119 } 120 } 121 } 122 123 /** 124 * Called when a layout pass has occurred. 125 */ onPostLayout()126 void onPostLayout() { 127 if (mWin == null) { 128 return; 129 } 130 131 mTmpRect.set(mWin.getFrameLw()); 132 if (mFrameProvider != null) { 133 mFrameProvider.accept(mWin.getDisplayContent().mDisplayFrames, mWin, mTmpRect); 134 } else { 135 mTmpRect.inset(mWin.mGivenContentInsets); 136 } 137 mSource.setFrame(mTmpRect); 138 if (mControl != null) { 139 final Rect frame = mWin.getWindowFrames().mFrame; 140 if (mControl.setSurfacePosition(frame.left, frame.top)) { 141 mStateController.notifyControlChanged(mControllingWin); 142 } 143 } 144 setServerVisible(mWin.wouldBeVisibleIfPolicyIgnored() && mWin.isVisibleByPolicy() 145 && !mWin.mGivenInsetsPending); 146 } 147 updateControlForTarget(@ullable WindowState target, boolean force)148 void updateControlForTarget(@Nullable WindowState target, boolean force) { 149 if (mWin == null) { 150 mControllingWin = target; 151 return; 152 } 153 if (target == mControllingWin && !force) { 154 return; 155 } 156 if (target == null) { 157 // Cancelling the animation will invoke onAnimationCancelled, resetting all the fields. 158 mWin.cancelAnimation(); 159 return; 160 } 161 mAdapter = new ControlAdapter(); 162 setClientVisible(InsetsState.getDefaultVisibility(mSource.getType())); 163 mWin.startAnimation(mDisplayContent.getPendingTransaction(), mAdapter, 164 !mClientVisible /* hidden */); 165 mControllingWin = target; 166 mControl = new InsetsSourceControl(mSource.getType(), mAdapter.mCapturedLeash, 167 new Point(mWin.getWindowFrames().mFrame.left, mWin.getWindowFrames().mFrame.top)); 168 } 169 onInsetsModified(WindowState caller, InsetsSource modifiedSource)170 boolean onInsetsModified(WindowState caller, InsetsSource modifiedSource) { 171 if (mControllingWin != caller || modifiedSource.isVisible() == mClientVisible) { 172 return false; 173 } 174 setClientVisible(modifiedSource.isVisible()); 175 return true; 176 } 177 setClientVisible(boolean clientVisible)178 private void setClientVisible(boolean clientVisible) { 179 if (mClientVisible == clientVisible) { 180 return; 181 } 182 mClientVisible = clientVisible; 183 mDisplayContent.mWmService.mH.sendMessage(PooledLambda.obtainMessage( 184 DisplayContent::layoutAndAssignWindowLayersIfNeeded, mDisplayContent)); 185 updateVisibility(); 186 } 187 setServerVisible(boolean serverVisible)188 private void setServerVisible(boolean serverVisible) { 189 mServerVisible = serverVisible; 190 updateVisibility(); 191 } 192 updateVisibility()193 private void updateVisibility() { 194 mSource.setVisible(mServerVisible && mClientVisible); 195 } 196 getControl()197 InsetsSourceControl getControl() { 198 return mControl; 199 } 200 isClientVisible()201 boolean isClientVisible() { 202 return sNewInsetsMode == NEW_INSETS_MODE_NONE || mClientVisible; 203 } 204 205 private class ControlAdapter implements AnimationAdapter { 206 207 private SurfaceControl mCapturedLeash; 208 209 @Override getShowWallpaper()210 public boolean getShowWallpaper() { 211 return false; 212 } 213 214 @Override getBackgroundColor()215 public int getBackgroundColor() { 216 return 0; 217 } 218 219 @Override startAnimation(SurfaceControl animationLeash, Transaction t, OnAnimationFinishedCallback finishCallback)220 public void startAnimation(SurfaceControl animationLeash, Transaction t, 221 OnAnimationFinishedCallback finishCallback) { 222 mCapturedLeash = animationLeash; 223 final Rect frame = mWin.getWindowFrames().mFrame; 224 t.setPosition(mCapturedLeash, frame.left, frame.top); 225 } 226 227 @Override onAnimationCancelled(SurfaceControl animationLeash)228 public void onAnimationCancelled(SurfaceControl animationLeash) { 229 if (mAdapter == this) { 230 mStateController.notifyControlRevoked(mControllingWin, InsetsSourceProvider.this); 231 setClientVisible(InsetsState.getDefaultVisibility(mSource.getType())); 232 mControl = null; 233 mControllingWin = null; 234 mAdapter = null; 235 } 236 } 237 238 @Override getDurationHint()239 public long getDurationHint() { 240 return 0; 241 } 242 243 @Override getStatusBarTransitionsStartTime()244 public long getStatusBarTransitionsStartTime() { 245 return 0; 246 } 247 248 @Override dump(PrintWriter pw, String prefix)249 public void dump(PrintWriter pw, String prefix) { 250 } 251 252 @Override writeToProto(ProtoOutputStream proto)253 public void writeToProto(ProtoOutputStream proto) { 254 } 255 }; 256 } 257