1 /*
2  * Copyright (C) 2017 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 test.windowmanagerstresstest;
18 
19 import android.app.Activity;
20 import android.graphics.Rect;
21 import android.os.Bundle;
22 import android.os.RemoteException;
23 import android.os.SystemClock;
24 import android.util.Log;
25 import android.util.MergedConfiguration;
26 import android.view.Display;
27 import android.view.DisplayCutout;
28 import android.view.IWindowSession;
29 import android.view.InsetsState;
30 import android.view.Surface;
31 import android.view.SurfaceControl;
32 import android.view.View;
33 import android.view.WindowManager;
34 import android.view.WindowManager.LayoutParams;
35 import android.view.WindowManagerGlobal;
36 import android.widget.TextView;
37 
38 import com.android.internal.view.BaseIWindow;
39 
40 import java.util.ArrayList;
41 
42 public class MainActivity extends Activity {
43 
44     private static final String TAG = "WmSlam";
45 
46     private TextView mOutput;
47     private volatile boolean finished;
48     private final ArrayList<BaseIWindow> mWindows = new ArrayList<>();
49     private final LayoutParams mLayoutParams = new LayoutParams();
50     private final Rect mTmpRect = new Rect();
51 
52     @Override
onCreate(Bundle savedInstanceState)53     protected void onCreate(Bundle savedInstanceState) {
54         super.onCreate(savedInstanceState);
55         setContentView(R.layout.activity_main);
56         mOutput = (TextView) findViewById(R.id.output);
57 
58         findViewById(R.id.run).setOnClickListener(view -> {
59             view.setEnabled(false);
60             mOutput.setText("");
61             startBatch();
62         });
63         mLayoutParams.token = getActivityToken();
64     }
65 
startBatch()66     void startBatch() {
67         new Thread(() -> {
68             finished = false;
69             addWindows();
70             startCpuRunnables();
71             for (int i = 0; i < 5; i++) {
72                 final long time = SystemClock.uptimeMillis();
73                 slamWm();
74                 log("Total: " + (SystemClock.uptimeMillis() - time) + " ms");
75             }
76             removeWindows();
77             finished = true;
78         }).start();
79     }
80 
startCpuRunnables()81     void startCpuRunnables() {
82         for (int i = 0; i < 10; i++) {
83             new Thread(mUseCpuRunnable).start();
84         }
85     }
86 
87     private final Runnable mUseCpuRunnable = new Runnable() {
88         @Override
89         public void run() {
90             while (!finished) {
91             }
92         }
93     };
94 
log(String text)95     private void log(String text) {
96         mOutput.post(() -> mOutput.append(text + "\n"));
97         Log.d(TAG, text);
98     }
99 
slamWm()100     private void slamWm() {
101         ArrayList<Thread> threads = new ArrayList<>();
102         for (int i = 0; i < 20; i++) {
103             for (BaseIWindow window : mWindows) {
104                 Thread t = new Thread(() -> {
105                     try {
106                         WindowManagerGlobal.getWindowSession().relayout(window,
107                                 window.mSeq, mLayoutParams, -1, -1, View.VISIBLE, 0, -1, mTmpRect,
108                                 mTmpRect, mTmpRect, mTmpRect, mTmpRect, mTmpRect, mTmpRect,
109                                 new DisplayCutout.ParcelableWrapper(), new MergedConfiguration(),
110                                 new SurfaceControl(), new InsetsState());
111                     } catch (RemoteException e) {
112                         e.printStackTrace();
113                     }
114                 });
115                 threads.add(t);
116                 t.start();
117             }
118         }
119         for (Thread t : threads) {
120             try {
121                 t.join();
122             } catch (InterruptedException e) {
123                 e.printStackTrace();
124             }
125         }
126     }
127 
addWindows()128     void addWindows() {
129         for (int i = 0; i < 50; i++) {
130             final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
131             layoutParams.token = getActivityToken();
132             final BaseIWindow window = new BaseIWindow();
133             final IWindowSession session = WindowManagerGlobal.getWindowSession();
134             final Rect tmpRect = new Rect();
135             try {
136                 final int res = session.addToDisplayWithoutInputChannel(window, window.mSeq,
137                         layoutParams, View.VISIBLE, Display.DEFAULT_DISPLAY, tmpRect, tmpRect,
138                         new InsetsState());
139             } catch (RemoteException e) {
140                 e.printStackTrace();
141             }
142             mWindows.add(window);
143         }
144     }
145 
removeWindows()146     void removeWindows() {
147         for (BaseIWindow window : mWindows) {
148             try {
149                 WindowManagerGlobal.getWindowSession().remove(window);
150             } catch (RemoteException e) {
151                 e.printStackTrace();
152             }
153         }
154     }
155 }
156