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