1 /*
2  * Copyright (C) 2015 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.systemui.stackdivider;
18 
19 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
20 import static android.view.WindowManager.DOCKED_INVALID;
21 
22 import android.app.ActivityManagerNative;
23 import android.graphics.Rect;
24 import android.os.RemoteException;
25 import android.util.Log;
26 import android.view.WindowManagerGlobal;
27 
28 import com.android.internal.annotations.GuardedBy;
29 
30 import java.util.concurrent.ExecutorService;
31 import java.util.concurrent.Executors;
32 
33 /**
34  * Proxy to simplify calls into window manager/activity manager
35  */
36 public class WindowManagerProxy {
37 
38     private static final String TAG = "WindowManagerProxy";
39 
40     private static final WindowManagerProxy sInstance = new WindowManagerProxy();
41 
42     @GuardedBy("mDockedRect")
43     private final Rect mDockedRect = new Rect();
44     private final Rect mTempDockedTaskRect = new Rect();
45     private final Rect mTempDockedInsetRect = new Rect();
46     private final Rect mTempOtherTaskRect = new Rect();
47     private final Rect mTempOtherInsetRect = new Rect();
48 
49     private final Rect mTmpRect1 = new Rect();
50     private final Rect mTmpRect2 = new Rect();
51     private final Rect mTmpRect3 = new Rect();
52     private final Rect mTmpRect4 = new Rect();
53     private final Rect mTmpRect5 = new Rect();
54 
55     @GuardedBy("mDockedRect")
56     private final Rect mTouchableRegion = new Rect();
57 
58     private boolean mDimLayerVisible;
59     private int mDimLayerTargetStack;
60     private float mDimLayerAlpha;
61 
62     private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
63 
64     private final Runnable mResizeRunnable = new Runnable() {
65         @Override
66         public void run() {
67             synchronized (mDockedRect) {
68                 mTmpRect1.set(mDockedRect);
69                 mTmpRect2.set(mTempDockedTaskRect);
70                 mTmpRect3.set(mTempDockedInsetRect);
71                 mTmpRect4.set(mTempOtherTaskRect);
72                 mTmpRect5.set(mTempOtherInsetRect);
73             }
74             try {
75                 ActivityManagerNative.getDefault()
76                         .resizeDockedStack(mTmpRect1,
77                                 mTmpRect2.isEmpty() ? null : mTmpRect2,
78                                 mTmpRect3.isEmpty() ? null : mTmpRect3,
79                                 mTmpRect4.isEmpty() ? null : mTmpRect4,
80                                 mTmpRect5.isEmpty() ? null : mTmpRect5);
81             } catch (RemoteException e) {
82                 Log.w(TAG, "Failed to resize stack: " + e);
83             }
84         }
85     };
86 
87     private final Runnable mDismissRunnable = new Runnable() {
88         @Override
89         public void run() {
90             try {
91                 ActivityManagerNative.getDefault().moveTasksToFullscreenStack(
92                         DOCKED_STACK_ID, false /* onTop */);
93             } catch (RemoteException e) {
94                 Log.w(TAG, "Failed to remove stack: " + e);
95             }
96         }
97     };
98 
99     private final Runnable mMaximizeRunnable = new Runnable() {
100         @Override
101         public void run() {
102             try {
103                 ActivityManagerNative.getDefault().resizeStack(
104                         DOCKED_STACK_ID, null, true, true, false, -1);
105             } catch (RemoteException e) {
106                 Log.w(TAG, "Failed to resize stack: " + e);
107             }
108         }
109     };
110 
111     private final Runnable mDimLayerRunnable = new Runnable() {
112         @Override
113         public void run() {
114             try {
115                 WindowManagerGlobal.getWindowManagerService().setResizeDimLayer(mDimLayerVisible,
116                         mDimLayerTargetStack, mDimLayerAlpha);
117             } catch (RemoteException e) {
118                 Log.w(TAG, "Failed to resize stack: " + e);
119             }
120         }
121     };
122 
123     private final Runnable mSwapRunnable = new Runnable() {
124         @Override
125         public void run() {
126             try {
127                 ActivityManagerNative.getDefault().swapDockedAndFullscreenStack();
128             } catch (RemoteException e) {
129                 Log.w(TAG, "Failed to resize stack: " + e);
130             }
131         }
132     };
133 
134     private final Runnable mSetTouchableRegionRunnable = new Runnable() {
135         @Override
136         public void run() {
137             try {
138                 synchronized (mDockedRect) {
139                     mTmpRect1.set(mTouchableRegion);
140                 }
141                 WindowManagerGlobal.getWindowManagerService().setDockedStackDividerTouchRegion(
142                         mTmpRect1);
143             } catch (RemoteException e) {
144                 Log.w(TAG, "Failed to set touchable region: " + e);
145             }
146         }
147     };
148 
WindowManagerProxy()149     private WindowManagerProxy() {
150     }
151 
getInstance()152     public static WindowManagerProxy getInstance() {
153         return sInstance;
154     }
155 
resizeDockedStack(Rect docked, Rect tempDockedTaskRect, Rect tempDockedInsetRect, Rect tempOtherTaskRect, Rect tempOtherInsetRect)156     public void resizeDockedStack(Rect docked, Rect tempDockedTaskRect, Rect tempDockedInsetRect,
157             Rect tempOtherTaskRect, Rect tempOtherInsetRect) {
158         synchronized (mDockedRect) {
159             mDockedRect.set(docked);
160             if (tempDockedTaskRect != null) {
161                 mTempDockedTaskRect.set(tempDockedTaskRect);
162             } else {
163                 mTempDockedTaskRect.setEmpty();
164             }
165             if (tempDockedInsetRect != null) {
166                 mTempDockedInsetRect.set(tempDockedInsetRect);
167             } else {
168                 mTempDockedInsetRect.setEmpty();
169             }
170             if (tempOtherTaskRect != null) {
171                 mTempOtherTaskRect.set(tempOtherTaskRect);
172             } else {
173                 mTempOtherTaskRect.setEmpty();
174             }
175             if (tempOtherInsetRect != null) {
176                 mTempOtherInsetRect.set(tempOtherInsetRect);
177             } else {
178                 mTempOtherInsetRect.setEmpty();
179             }
180         }
181         mExecutor.execute(mResizeRunnable);
182     }
183 
dismissDockedStack()184     public void dismissDockedStack() {
185         mExecutor.execute(mDismissRunnable);
186     }
187 
maximizeDockedStack()188     public void maximizeDockedStack() {
189         mExecutor.execute(mMaximizeRunnable);
190     }
191 
setResizing(final boolean resizing)192     public void setResizing(final boolean resizing) {
193         mExecutor.execute(new Runnable() {
194             @Override
195             public void run() {
196                 try {
197                     WindowManagerGlobal.getWindowManagerService().setDockedStackResizing(resizing);
198                 } catch (RemoteException e) {
199                     Log.w(TAG, "Error calling setDockedStackResizing: " + e);
200                 }
201             }
202         });
203     }
204 
getDockSide()205     public int getDockSide() {
206         try {
207             return WindowManagerGlobal.getWindowManagerService().getDockedStackSide();
208         } catch (RemoteException e) {
209             Log.w(TAG, "Failed to get dock side: " + e);
210         }
211         return DOCKED_INVALID;
212     }
213 
setResizeDimLayer(boolean visible, int targetStackId, float alpha)214     public void setResizeDimLayer(boolean visible, int targetStackId, float alpha) {
215         mDimLayerVisible = visible;
216         mDimLayerTargetStack = targetStackId;
217         mDimLayerAlpha = alpha;
218         mExecutor.execute(mDimLayerRunnable);
219     }
220 
swapTasks()221     public void swapTasks() {
222         mExecutor.execute(mSwapRunnable);
223     }
224 
setTouchRegion(Rect region)225     public void setTouchRegion(Rect region) {
226         synchronized (mDockedRect) {
227             mTouchableRegion.set(region);
228         }
229         mExecutor.execute(mSetTouchableRegionRunnable);
230     }
231 }
232