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