blob: 412a4550015739556ed883df65ba22ac94baf3b8 [file] [log] [blame]
Filip Gruszczynski466f3212015-09-21 17:57:57 -07001/*
2 * Copyright (C) 2012 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
17package com.android.server.wm;
18
Filip Gruszczynski466f3212015-09-21 17:57:57 -070019import android.content.Context;
Filip Gruszczynski466f3212015-09-21 17:57:57 -070020import android.graphics.Rect;
Jorim Jaggia6c934e2015-12-21 13:22:31 +010021import android.os.RemoteCallbackList;
Filip Gruszczynski64cdc142015-11-29 21:10:07 -080022import android.os.RemoteException;
Filip Gruszczynski77049052015-11-09 14:01:21 -080023import android.util.Slog;
Jorim Jaggi50981592015-12-29 17:54:12 +010024import android.view.DisplayInfo;
Jorim Jaggia6c934e2015-12-21 13:22:31 +010025import android.view.IDockedStackListener;
Jorim Jaggi50981592015-12-29 17:54:12 +010026import android.view.SurfaceControl;
27
28import com.android.server.wm.DimLayer.DimLayerUser;
Jorim Jaggi61f39a72015-10-29 16:54:18 +010029
Jorim Jaggie48f4282015-11-06 17:32:44 +010030import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
Jorim Jaggi50981592015-12-29 17:54:12 +010031import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
Jorim Jaggi61f39a72015-10-29 16:54:18 +010032import static android.view.WindowManager.DOCKED_BOTTOM;
33import static android.view.WindowManager.DOCKED_LEFT;
34import static android.view.WindowManager.DOCKED_RIGHT;
35import static android.view.WindowManager.DOCKED_TOP;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080036import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
37import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Filip Gruszczynski466f3212015-09-21 17:57:57 -070038
39/**
Jorim Jaggi61f39a72015-10-29 16:54:18 +010040 * Keeps information about the docked stack divider.
Filip Gruszczynski466f3212015-09-21 17:57:57 -070041 */
Jorim Jaggi50981592015-12-29 17:54:12 +010042public class DockedStackDividerController implements DimLayerUser {
Jorim Jaggi61f39a72015-10-29 16:54:18 +010043
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080044 private static final String TAG = TAG_WITH_CLASS_NAME ? "DockedStackDividerController" : TAG_WM;
Jorim Jaggi61f39a72015-10-29 16:54:18 +010045
Filip Gruszczynski466f3212015-09-21 17:57:57 -070046 private final DisplayContent mDisplayContent;
Jorim Jaggi1fcbab62015-11-04 16:39:50 +010047 private final int mDividerWindowWidth;
48 private final int mDividerInsets;
Jorim Jaggi61f39a72015-10-29 16:54:18 +010049 private boolean mResizing;
50 private WindowState mWindow;
51 private final Rect mTmpRect = new Rect();
Filip Gruszczynski77049052015-11-09 14:01:21 -080052 private final Rect mLastRect = new Rect();
Filip Gruszczynski64cdc142015-11-29 21:10:07 -080053 private boolean mLastVisibility = false;
Jorim Jaggia6c934e2015-12-21 13:22:31 +010054 private final RemoteCallbackList<IDockedStackListener> mDockedStackListeners
55 = new RemoteCallbackList<>();
Jorim Jaggi50981592015-12-29 17:54:12 +010056 private final DimLayer mDimLayer;
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -070057
Filip Gruszczynski466f3212015-09-21 17:57:57 -070058 DockedStackDividerController(Context context, DisplayContent displayContent) {
Filip Gruszczynski466f3212015-09-21 17:57:57 -070059 mDisplayContent = displayContent;
Jorim Jaggi1fcbab62015-11-04 16:39:50 +010060 mDividerWindowWidth = context.getResources().getDimensionPixelSize(
Filip Gruszczynski466f3212015-09-21 17:57:57 -070061 com.android.internal.R.dimen.docked_stack_divider_thickness);
Jorim Jaggi1fcbab62015-11-04 16:39:50 +010062 mDividerInsets = context.getResources().getDimensionPixelSize(
63 com.android.internal.R.dimen.docked_stack_divider_insets);
Jorim Jaggi50981592015-12-29 17:54:12 +010064 mDimLayer = new DimLayer(displayContent.mService, this, displayContent.getDisplayId());
Filip Gruszczynski466f3212015-09-21 17:57:57 -070065 }
66
Jorim Jaggi61f39a72015-10-29 16:54:18 +010067 boolean isResizing() {
68 return mResizing;
Filip Gruszczynski466f3212015-09-21 17:57:57 -070069 }
70
Jorim Jaggi1fcbab62015-11-04 16:39:50 +010071 int getContentWidth() {
72 return mDividerWindowWidth - 2 * mDividerInsets;
Filip Gruszczynski466f3212015-09-21 17:57:57 -070073 }
74
Jorim Jaggi81ba11e2016-02-03 22:04:22 -080075 int getContentInsets() {
76 return mDividerInsets;
77 }
78
Jorim Jaggi61f39a72015-10-29 16:54:18 +010079 void setResizing(boolean resizing) {
80 mResizing = resizing;
81 }
82
83 void setWindow(WindowState window) {
84 mWindow = window;
Filip Gruszczynski85d5cc42015-12-04 09:21:37 -080085 reevaluateVisibility(false);
Jorim Jaggi61f39a72015-10-29 16:54:18 +010086 }
87
Filip Gruszczynski85d5cc42015-12-04 09:21:37 -080088 void reevaluateVisibility(boolean force) {
Filip Gruszczynski64cdc142015-11-29 21:10:07 -080089 if (mWindow == null) {
90 return;
91 }
Jorim Jaggie48f4282015-11-06 17:32:44 +010092 TaskStack stack = mDisplayContent.mService.mStackIdToStack.get(DOCKED_STACK_ID);
Filip Gruszczynski64cdc142015-11-29 21:10:07 -080093 final boolean visible = stack != null && stack.isVisibleLocked();
Filip Gruszczynski85d5cc42015-12-04 09:21:37 -080094 if (mLastVisibility == visible && !force) {
Filip Gruszczynski64cdc142015-11-29 21:10:07 -080095 return;
96 }
97 mLastVisibility = visible;
Jorim Jaggia6c934e2015-12-21 13:22:31 +010098 notifyDockedDividerVisibilityChanged(visible);
Jorim Jaggi50981592015-12-29 17:54:12 +010099 if (!visible) {
100 setResizeDimLayer(false, INVALID_STACK_ID, 0f);
101 }
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100102 }
103
104 boolean wasVisible() {
105 return mLastVisibility;
Jorim Jaggi61f39a72015-10-29 16:54:18 +0100106 }
107
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700108 void positionDockedStackedDivider(Rect frame) {
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -0700109 TaskStack stack = mDisplayContent.getDockedStackLocked();
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700110 if (stack == null) {
111 // Unfortunately we might end up with still having a divider, even though the underlying
112 // stack was already removed. This is because we are on AM thread and the removal of the
Filip Gruszczynski77049052015-11-09 14:01:21 -0800113 // divider was deferred to WM thread and hasn't happened yet. In that case let's just
114 // keep putting it in the same place it was before the stack was removed to have
115 // continuity and prevent it from jumping to the center. It will get hidden soon.
116 frame.set(mLastRect);
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700117 return;
Filip Gruszczynski77049052015-11-09 14:01:21 -0800118 } else {
Chong Zhang4c9ba52a2015-11-10 18:36:33 -0800119 stack.getDimBounds(mTmpRect);
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700120 }
Jorim Jaggi61f39a72015-10-29 16:54:18 +0100121 int side = stack.getDockSide();
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700122 switch (side) {
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -0700123 case DOCKED_LEFT:
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100124 frame.set(mTmpRect.right - mDividerInsets, frame.top,
125 mTmpRect.right + frame.width() - mDividerInsets, frame.bottom);
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700126 break;
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -0700127 case DOCKED_TOP:
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100128 frame.set(frame.left, mTmpRect.bottom - mDividerInsets,
129 mTmpRect.right, mTmpRect.bottom + frame.height() - mDividerInsets);
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700130 break;
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -0700131 case DOCKED_RIGHT:
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100132 frame.set(mTmpRect.left - frame.width() + mDividerInsets, frame.top,
133 mTmpRect.left + mDividerInsets, frame.bottom);
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700134 break;
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -0700135 case DOCKED_BOTTOM:
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100136 frame.set(frame.left, mTmpRect.top - frame.height() + mDividerInsets,
137 frame.right, mTmpRect.top + mDividerInsets);
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700138 break;
139 }
Filip Gruszczynski77049052015-11-09 14:01:21 -0800140 mLastRect.set(frame);
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700141 }
Filip Gruszczynski64cdc142015-11-29 21:10:07 -0800142
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100143 void notifyDockedDividerVisibilityChanged(boolean visible) {
144 final int size = mDockedStackListeners.beginBroadcast();
145 for (int i = 0; i < size; ++i) {
146 final IDockedStackListener listener = mDockedStackListeners.getBroadcastItem(i);
147 try {
148 listener.onDividerVisibilityChanged(visible);
149 } catch (RemoteException e) {
150 Slog.e(TAG_WM, "Error delivering divider visibility changed event.", e);
151 }
Filip Gruszczynski64cdc142015-11-29 21:10:07 -0800152 }
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100153 mDockedStackListeners.finishBroadcast();
154 }
155
156 void notifyDockedStackExistsChanged(boolean exists) {
157 final int size = mDockedStackListeners.beginBroadcast();
158 for (int i = 0; i < size; ++i) {
159 final IDockedStackListener listener = mDockedStackListeners.getBroadcastItem(i);
160 try {
161 listener.onDockedStackExistsChanged(exists);
162 } catch (RemoteException e) {
163 Slog.e(TAG_WM, "Error delivering docked stack exists changed event.", e);
164 }
165 }
166 mDockedStackListeners.finishBroadcast();
167 }
168
169 void registerDockedStackListener(IDockedStackListener listener) {
170 mDockedStackListeners.register(listener);
171 notifyDockedDividerVisibilityChanged(wasVisible());
172 notifyDockedStackExistsChanged(
173 mDisplayContent.mService.mStackIdToStack.get(DOCKED_STACK_ID) != null);
Filip Gruszczynski64cdc142015-11-29 21:10:07 -0800174 }
Jorim Jaggi50981592015-12-29 17:54:12 +0100175
176 void setResizeDimLayer(boolean visible, int targetStackId, float alpha) {
177 SurfaceControl.openTransaction();
178 TaskStack stack = mDisplayContent.mService.mStackIdToStack.get(targetStackId);
Jorim Jaggi7b371dd2016-01-05 15:32:34 +0100179 boolean visibleAndValid = visible && stack != null;
180 if (visibleAndValid) {
Jorim Jaggi50981592015-12-29 17:54:12 +0100181 stack.getDimBounds(mTmpRect);
Jorim Jaggi10b89dc2016-01-05 15:40:17 +0100182 if (mTmpRect.height() > 0 && mTmpRect.width() > 0) {
Jorim Jaggi7b371dd2016-01-05 15:32:34 +0100183 mDimLayer.setBounds(mTmpRect);
184 mDimLayer.show(mDisplayContent.mService.mLayersController.getResizeDimLayer(),
185 alpha, 0 /* duration */);
186 } else {
187 visibleAndValid = false;
188 }
189 }
190 if (!visibleAndValid) {
Jorim Jaggi50981592015-12-29 17:54:12 +0100191 mDimLayer.hide();
192 }
193 SurfaceControl.closeTransaction();
194 }
195
196 @Override
197 public boolean isFullscreen() {
198 return false;
199 }
200
201 @Override
202 public DisplayInfo getDisplayInfo() {
203 return mDisplayContent.getDisplayInfo();
204 }
205
206 @Override
207 public void getDimBounds(Rect outBounds) {
208 // This dim layer user doesn't need this.
209 }
210
211 @Override
212 public String toShortString() {
213 return TAG;
214 }
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700215}