OLD | NEW |
| (Empty) |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 package org.chromium.content.browser; | |
6 | |
7 import static android.content.ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL; | |
8 import static android.content.ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW; | |
9 import static android.content.ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE; | |
10 | |
11 import android.app.Activity; | |
12 import android.app.Application; | |
13 import android.util.Pair; | |
14 | |
15 import org.junit.After; | |
16 import org.junit.Assert; | |
17 import org.junit.Before; | |
18 import org.junit.Test; | |
19 import org.junit.runner.RunWith; | |
20 import org.robolectric.Robolectric; | |
21 import org.robolectric.annotation.Config; | |
22 import org.robolectric.shadows.ShadowLooper; | |
23 | |
24 import org.chromium.base.process_launcher.ChildProcessCreationParams; | |
25 import org.chromium.base.test.util.Feature; | |
26 import org.chromium.testing.local.LocalRobolectricTestRunner; | |
27 | |
28 import java.util.ArrayList; | |
29 | |
30 /** | |
31 * Unit tests for BindingManagerImpl. The tests run agains mock ChildProcessConn
ection | |
32 * implementation, thus testing only the BindingManagerImpl itself. | |
33 * | |
34 * Default property of being low-end device is overriden, so that both low-end a
nd high-end policies | |
35 * are tested. | |
36 */ | |
37 @RunWith(LocalRobolectricTestRunner.class) | |
38 @Config(manifest = Config.NONE) | |
39 public class BindingManagerImplTest { | |
40 private static class MockChildServiceConnection | |
41 implements BaseChildProcessConnection.ChildServiceConnection { | |
42 private boolean mBound; | |
43 | |
44 @Override | |
45 public boolean bind() { | |
46 mBound = true; | |
47 return true; | |
48 } | |
49 | |
50 @Override | |
51 public void unbind() { | |
52 mBound = false; | |
53 } | |
54 | |
55 @Override | |
56 public boolean isBound() { | |
57 return mBound; | |
58 } | |
59 } | |
60 | |
61 private static class TestChildProcessConnection extends ManagedChildProcessC
onnection { | |
62 private final int mPid; | |
63 private boolean mConnected; | |
64 | |
65 /** | |
66 * Creates a mock binding corresponding to real ManagedChildProcessConne
ction after the | |
67 * connection is established: with initial binding bound and no strong b
inding. | |
68 */ | |
69 private TestChildProcessConnection(int pid) { | |
70 super(null /* context */, pid /* number */, true /* sandboxed */, | |
71 null /* deathCallback */, null /* serviceClassName */, | |
72 null /* childProcessCommonParameters */, | |
73 new ChildProcessCreationParams("org.chromium.test", | |
74 false /* isExternalService */, 0 /* libraryProcessTy
pe */, | |
75 false /* bindToCallerCheck */)); | |
76 mPid = pid; | |
77 } | |
78 | |
79 @Override | |
80 public int getPid() { | |
81 return mPid; | |
82 } | |
83 | |
84 @Override | |
85 protected ChildServiceConnection createServiceConnection(int bindFlags)
{ | |
86 return new MockChildServiceConnection(); | |
87 } | |
88 | |
89 // We don't have a real service so we have to mock the connection status
. | |
90 @Override | |
91 public void start(StartCallback startCallback) { | |
92 super.start(startCallback); | |
93 mConnected = true; | |
94 } | |
95 | |
96 @Override | |
97 public void stop() { | |
98 super.stop(); | |
99 mConnected = false; | |
100 } | |
101 | |
102 @Override | |
103 public boolean isConnected() { | |
104 return mConnected; | |
105 } | |
106 } | |
107 | |
108 /** | |
109 * Helper class that stores a manager along with its text label. This is use
d for tests that | |
110 * iterate over all managers to indicate which manager was being tested when
an assertion | |
111 * failed. | |
112 */ | |
113 private static class ManagerEntry { | |
114 BindingManagerImpl mManager; | |
115 String mLabel; // Name of the manager. | |
116 | |
117 ManagerEntry(BindingManagerImpl manager, String label) { | |
118 mManager = manager; | |
119 mLabel = label; | |
120 } | |
121 | |
122 String getErrorMessage() { | |
123 return "Failed for the " + mLabel + " manager."; | |
124 } | |
125 } | |
126 | |
127 Activity mActivity; | |
128 | |
129 // The managers are created in setUp() for convenience. | |
130 BindingManagerImpl mLowEndManager; | |
131 BindingManagerImpl mHighEndManager; | |
132 BindingManagerImpl mModerateBindingManager; | |
133 ManagerEntry[] mAllManagers; | |
134 | |
135 @Before | |
136 public void setUp() { | |
137 // The tests run on only one thread. Pretend that is the launcher thread
so LauncherThread | |
138 // asserts are not triggered. | |
139 LauncherThread.setCurrentThreadAsLauncherThread(); | |
140 | |
141 mActivity = Robolectric.buildActivity(Activity.class).setup().get(); | |
142 | |
143 mLowEndManager = | |
144 BindingManagerImpl.createBindingManagerForTesting(true /* isLowE
ndDevice */); | |
145 mHighEndManager = | |
146 BindingManagerImpl.createBindingManagerForTesting(false /* isLow
EndDevice */); | |
147 mModerateBindingManager = | |
148 BindingManagerImpl.createBindingManagerForTesting(false /* isLow
EndDevice */); | |
149 mModerateBindingManager.startModerateBindingManagement(mActivity, 4 /* m
axSize */); | |
150 mAllManagers = new ManagerEntry[] { | |
151 new ManagerEntry(mLowEndManager, "low-end"), | |
152 new ManagerEntry(mHighEndManager, "high-end"), | |
153 new ManagerEntry(mModerateBindingManager, "moderate-binding")}; | |
154 } | |
155 | |
156 @After | |
157 public void tearDown() { | |
158 LauncherThread.setLauncherThreadAsLauncherThread(); | |
159 } | |
160 | |
161 /** | |
162 * Verifies that when running on low-end, the binding manager drops the oom
bindings for the | |
163 * previously bound connection when a new connection is used in foreground. | |
164 */ | |
165 @Test | |
166 @Feature({"ProcessManagement"}) | |
167 public void testNewConnectionDropsPreviousOnLowEnd() { | |
168 // This test applies only to the low-end manager. | |
169 BindingManagerImpl manager = mLowEndManager; | |
170 | |
171 // Add a connection to the manager. | |
172 TestChildProcessConnection firstConnection = new TestChildProcessConnect
ion(1); | |
173 firstConnection.start(null /* startCallback */); | |
174 manager.addNewConnection(firstConnection.getPid(), firstConnection); | |
175 | |
176 // Bind a strong binding on the connection. | |
177 manager.setInForeground(firstConnection.getPid(), true); | |
178 Assert.assertTrue(firstConnection.isStrongBindingBound()); | |
179 | |
180 // Add a new connection. | |
181 TestChildProcessConnection secondConnection = new TestChildProcessConnec
tion(2); | |
182 secondConnection.start(null /* startCallback */); | |
183 manager.addNewConnection(secondConnection.getPid(), secondConnection); | |
184 | |
185 // Verify that the strong binding for the first connection wasn't droppe
d. | |
186 Assert.assertTrue(firstConnection.isStrongBindingBound()); | |
187 | |
188 // Verify that the strong binding for the first connection was dropped w
hen a new connection | |
189 // got used in foreground. | |
190 manager.setInForeground(secondConnection.getPid(), true); | |
191 Assert.assertFalse(firstConnection.isStrongBindingBound()); | |
192 } | |
193 | |
194 /** | |
195 * Verifies the strong binding removal policies for low end devices: | |
196 * - the initial binding should not be affected | |
197 * - removal of a strong binding should be executed synchronously | |
198 */ | |
199 @Test | |
200 @Feature({"ProcessManagement"}) | |
201 public void testStrongBindingRemovalOnLowEnd() throws Throwable { | |
202 // This test applies only to the low-end manager. | |
203 final BindingManagerImpl manager = mLowEndManager; | |
204 | |
205 // Add a connection to the manager. | |
206 final TestChildProcessConnection connection = new TestChildProcessConnec
tion(1); | |
207 connection.start(null /* startCallback */); | |
208 manager.addNewConnection(connection.getPid(), connection); | |
209 Assert.assertTrue(connection.isInitialBindingBound()); | |
210 Assert.assertFalse(connection.isStrongBindingBound()); | |
211 | |
212 // Add a strong binding, verify that the initial binding is not removed. | |
213 manager.setInForeground(connection.getPid(), true); | |
214 Assert.assertTrue(connection.isStrongBindingBound()); | |
215 Assert.assertTrue(connection.isInitialBindingBound()); | |
216 | |
217 // Remove the strong binding, verify that the strong binding is removed
immediately | |
218 // and that the initial binding is not affected. | |
219 manager.setInForeground(connection.getPid(), false); | |
220 Assert.assertFalse(connection.isStrongBindingBound()); | |
221 Assert.assertTrue(connection.isInitialBindingBound()); | |
222 } | |
223 | |
224 /** | |
225 * Verifies the strong binding removal policies for high end devices, where
the removal should | |
226 * be delayed. | |
227 */ | |
228 @Test | |
229 @Feature({"ProcessManagement"}) | |
230 public void testStrongBindingRemovalOnHighEnd() throws Throwable { | |
231 // This test applies only to the high-end manager. | |
232 final BindingManagerImpl manager = mHighEndManager; | |
233 | |
234 // Add a connection to the manager. | |
235 final TestChildProcessConnection connection = new TestChildProcessConnec
tion(1); | |
236 connection.start(null /* startCallback */); | |
237 manager.addNewConnection(connection.getPid(), connection); | |
238 Assert.assertTrue(connection.isInitialBindingBound()); | |
239 Assert.assertFalse(connection.isStrongBindingBound()); | |
240 | |
241 // Add a strong binding, verify that the initial binding is not removed. | |
242 manager.setInForeground(connection.getPid(), true); | |
243 Assert.assertTrue(connection.isStrongBindingBound()); | |
244 Assert.assertTrue(connection.isInitialBindingBound()); | |
245 | |
246 // Remove the strong binding, verify that the strong binding is not remo
ved | |
247 // immediately. | |
248 manager.setInForeground(connection.getPid(), false); | |
249 Assert.assertTrue(connection.isStrongBindingBound()); | |
250 Assert.assertTrue(connection.isInitialBindingBound()); | |
251 | |
252 // Wait until the posted unbinding tasks get executed and verify that th
e strong binding was | |
253 // removed while the initial binding is not affected. | |
254 ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); | |
255 Assert.assertFalse(connection.isStrongBindingBound()); | |
256 Assert.assertTrue(connection.isInitialBindingBound()); | |
257 } | |
258 | |
259 /** | |
260 * Verifies the strong binding removal policies with moderate binding manage
ment, where the | |
261 * moderate binding should be bound. | |
262 */ | |
263 @Test | |
264 @Feature({"ProcessManagement"}) | |
265 public void testStrongBindingRemovalWithModerateBinding() throws Throwable { | |
266 // This test applies only to the moderate-binding manager. | |
267 final BindingManagerImpl manager = mModerateBindingManager; | |
268 | |
269 // Add a connection to the manager and start it. | |
270 final TestChildProcessConnection connection = new TestChildProcessConnec
tion(1); | |
271 connection.start(null /* startCallback */); | |
272 manager.addNewConnection(connection.getPid(), connection); | |
273 | |
274 Assert.assertTrue(connection.isInitialBindingBound()); | |
275 Assert.assertFalse(connection.isStrongBindingBound()); | |
276 Assert.assertFalse(connection.isModerateBindingBound()); | |
277 | |
278 // Add a strong binding, verify that the initial binding is not removed. | |
279 manager.setInForeground(connection.getPid(), true); | |
280 Assert.assertTrue(connection.isStrongBindingBound()); | |
281 Assert.assertTrue(connection.isInitialBindingBound()); | |
282 Assert.assertFalse(connection.isModerateBindingBound()); | |
283 | |
284 // Remove the strong binding, verify that the strong binding is not remo
ved | |
285 // immediately. | |
286 manager.setInForeground(connection.getPid(), false); | |
287 Assert.assertTrue(connection.isStrongBindingBound()); | |
288 Assert.assertTrue(connection.isInitialBindingBound()); | |
289 Assert.assertFalse(connection.isModerateBindingBound()); | |
290 | |
291 // Wait until the posted unbinding tasks get executed and verify that th
e strong binding was | |
292 // removed while the initial binding is not affected, and the moderate b
inding is bound. | |
293 ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); | |
294 Assert.assertFalse(connection.isStrongBindingBound()); | |
295 Assert.assertTrue(connection.isInitialBindingBound()); | |
296 Assert.assertTrue(connection.isModerateBindingBound()); | |
297 } | |
298 | |
299 /** | |
300 * Verifies that the initial binding is removed after onDeterminedVisibility
() is called. | |
301 */ | |
302 @Test | |
303 @Feature({"ProcessManagement"}) | |
304 public void testInitialBindingRemoval() { | |
305 // This test applies to low-end, high-end and moderate-binding policies. | |
306 for (ManagerEntry managerEntry : mAllManagers) { | |
307 BindingManagerImpl manager = managerEntry.mManager; | |
308 String message = managerEntry.getErrorMessage(); | |
309 | |
310 // Add a connection to the manager. | |
311 TestChildProcessConnection connection = new TestChildProcessConnecti
on(1); | |
312 connection.start(null /* startCallback */); | |
313 manager.addNewConnection(connection.getPid(), connection); | |
314 | |
315 // Verify that the initial binding is held. | |
316 Assert.assertTrue(connection.isInitialBindingBound()); | |
317 | |
318 // Call onDeterminedVisibility() and verify that the initial binding
was released. | |
319 manager.onDeterminedVisibility(connection.getPid()); | |
320 Assert.assertFalse(connection.isInitialBindingBound()); | |
321 } | |
322 } | |
323 | |
324 /** | |
325 * This test corresponds to a process crash scenario: after a process dies a
nd its connection is | |
326 * cleared, isOomProtectedOrWasWhenDied() may be called on the connection to
decide if it was a | |
327 * crash or out-of-memory kill. | |
328 */ | |
329 @Test | |
330 @Feature({"ProcessManagement"}) | |
331 public void testIsOomProtected() { | |
332 // This test applies to low-end, high-end and moderate-binding policies. | |
333 for (ManagerEntry managerEntry : mAllManagers) { | |
334 BindingManagerImpl manager = managerEntry.mManager; | |
335 String message = managerEntry.getErrorMessage(); | |
336 | |
337 // Add a connection to the manager. | |
338 TestChildProcessConnection connection = new TestChildProcessConnecti
on(1); | |
339 connection.start(null /* startCallback */); | |
340 manager.addNewConnection(connection.getPid(), connection); | |
341 | |
342 // Initial binding is an oom binding. | |
343 Assert.assertTrue(message, connection.isOomProtectedOrWasWhenDied())
; | |
344 | |
345 // After initial binding is removed, the connection is no longer oom
protected. | |
346 manager.setInForeground(connection.getPid(), false); | |
347 manager.onDeterminedVisibility(connection.getPid()); | |
348 ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); | |
349 Assert.assertFalse(message, connection.isOomProtectedOrWasWhenDied()
); | |
350 | |
351 // Add a strong binding, restoring the oom protection. | |
352 manager.setInForeground(connection.getPid(), true); | |
353 Assert.assertTrue(message, connection.isOomProtectedOrWasWhenDied())
; | |
354 | |
355 // Simulate a process crash - clear a connection in binding manager
and remove the | |
356 // bindings. | |
357 Assert.assertFalse(manager.isConnectionCleared(connection.getPid()))
; | |
358 manager.removeConnection(connection.getPid()); | |
359 Assert.assertTrue(manager.isConnectionCleared(connection.getPid())); | |
360 connection.stop(); | |
361 | |
362 // Verify that the connection doesn't keep any oom bindings, but the
manager reports the | |
363 // oom status as protected. | |
364 Assert.assertFalse(message, connection.isInitialBindingBound()); | |
365 Assert.assertFalse(message, connection.isStrongBindingBound()); | |
366 Assert.assertTrue(message, connection.isOomProtectedOrWasWhenDied())
; | |
367 } | |
368 } | |
369 | |
370 /** | |
371 * Verifies that onSentToBackground() / onBroughtToForeground() correctly at
tach and remove | |
372 * additional strong binding kept on the most recently bound renderer for th
e background | |
373 * period. | |
374 * | |
375 * The renderer that will be bound for the background period should be the o
ne that was most | |
376 * recendly bound using .setInForeground(), even if there is one that was ad
ded using | |
377 * .addNewConnection() after that. Otherwise we would bound a background ren
derer when user | |
378 * loads a new tab in background and leaves the browser. | |
379 */ | |
380 @Test | |
381 @Feature({"ProcessManagement"}) | |
382 public void testBackgroundPeriodBinding() { | |
383 // This test applies to low-end, high-end and moderate-binding policies. | |
384 for (ManagerEntry managerEntry : mAllManagers) { | |
385 BindingManagerImpl manager = managerEntry.mManager; | |
386 String message = managerEntry.getErrorMessage(); | |
387 | |
388 // Add two connections, bind and release each. | |
389 TestChildProcessConnection firstConnection = new TestChildProcessCon
nection(1); | |
390 firstConnection.start(null /* startCallback */); | |
391 manager.addNewConnection(firstConnection.getPid(), firstConnection); | |
392 manager.setInForeground(firstConnection.getPid(), true); | |
393 manager.setInForeground(firstConnection.getPid(), false); | |
394 | |
395 TestChildProcessConnection secondConnection = new TestChildProcessCo
nnection(2); | |
396 secondConnection.start(null /* startCallback */); | |
397 manager.addNewConnection(secondConnection.getPid(), secondConnection
); | |
398 manager.setInForeground(secondConnection.getPid(), true); | |
399 manager.setInForeground(secondConnection.getPid(), false); | |
400 | |
401 // Add third connection, do not bind it. | |
402 TestChildProcessConnection thirdConnection = new TestChildProcessCon
nection(3); | |
403 thirdConnection.start(null /* startCallback */); | |
404 manager.addNewConnection(thirdConnection.getPid(), thirdConnection); | |
405 manager.setInForeground(thirdConnection.getPid(), false); | |
406 | |
407 // Sanity check: verify that no connection has a strong binding. | |
408 ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); | |
409 Assert.assertFalse(message, firstConnection.isStrongBindingBound()); | |
410 Assert.assertFalse(message, secondConnection.isStrongBindingBound())
; | |
411 Assert.assertFalse(message, thirdConnection.isStrongBindingBound()); | |
412 | |
413 // Call onSentToBackground() and verify that a strong binding was ad
ded for the second | |
414 // connection: | |
415 // - not the first one, because it was bound earlier than the second | |
416 // - not the thirs one, because it was never bound at all | |
417 manager.onSentToBackground(); | |
418 Assert.assertFalse(message, firstConnection.isStrongBindingBound()); | |
419 Assert.assertTrue(message, secondConnection.isStrongBindingBound()); | |
420 Assert.assertFalse(message, thirdConnection.isStrongBindingBound()); | |
421 | |
422 // Call onBroughtToForeground() and verify that the strong binding w
as removed. | |
423 manager.onBroughtToForeground(); | |
424 ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); | |
425 Assert.assertFalse(message, firstConnection.isStrongBindingBound()); | |
426 Assert.assertFalse(message, secondConnection.isStrongBindingBound())
; | |
427 Assert.assertFalse(message, thirdConnection.isStrongBindingBound()); | |
428 } | |
429 } | |
430 | |
431 /** | |
432 * Verifies that onSentToBackground() drops all the moderate bindings after
some delay, and | |
433 * onBroughtToForeground() doesn't recover them. | |
434 */ | |
435 @Test | |
436 @Feature({"ProcessManagement"}) | |
437 public void testModerateBindingDropOnBackground() { | |
438 // This test applies only to the moderate-binding manager. | |
439 final BindingManagerImpl manager = mModerateBindingManager; | |
440 | |
441 TestChildProcessConnection[] connections = new TestChildProcessConnectio
n[3]; | |
442 for (int i = 0; i < connections.length; i++) { | |
443 connections[i] = new TestChildProcessConnection(i + 1); | |
444 connections[i].start(null /* startCallback */); | |
445 manager.addNewConnection(connections[i].getPid(), connections[i]); | |
446 } | |
447 | |
448 // Verify that each connection has a moderate binding after binding and
releasing a strong | |
449 // binding. | |
450 for (TestChildProcessConnection connection : connections) { | |
451 manager.setInForeground(connection.getPid(), true); | |
452 manager.setInForeground(connection.getPid(), false); | |
453 ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); | |
454 Assert.assertTrue(connection.isModerateBindingBound()); | |
455 } | |
456 | |
457 // Exclude lastInForeground because it will be kept in foreground when o
nSentToBackground() | |
458 // is called as |mLastInForeground|. | |
459 TestChildProcessConnection lastInForeground = new TestChildProcessConnec
tion(0); | |
460 manager.addNewConnection(lastInForeground.getPid(), lastInForeground); | |
461 lastInForeground.start(null /* startCallback */); | |
462 manager.setInForeground(lastInForeground.getPid(), true); | |
463 manager.setInForeground(lastInForeground.getPid(), false); | |
464 | |
465 ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); | |
466 | |
467 // Verify that leaving the application for a short time doesn't clear th
e moderate bindings. | |
468 manager.onSentToBackground(); | |
469 for (TestChildProcessConnection connection : connections) { | |
470 Assert.assertTrue(connection.isModerateBindingBound()); | |
471 } | |
472 Assert.assertTrue(lastInForeground.isStrongBindingBound()); | |
473 Assert.assertFalse(lastInForeground.isModerateBindingBound()); | |
474 manager.onBroughtToForeground(); | |
475 ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); | |
476 for (TestChildProcessConnection connection : connections) { | |
477 Assert.assertTrue(connection.isModerateBindingBound()); | |
478 } | |
479 | |
480 // Call onSentToBackground() and verify that all the moderate bindings d
rop after some | |
481 // delay. | |
482 manager.onSentToBackground(); | |
483 for (TestChildProcessConnection connection : connections) { | |
484 Assert.assertTrue(connection.isModerateBindingBound()); | |
485 } | |
486 Assert.assertTrue(lastInForeground.isStrongBindingBound()); | |
487 Assert.assertFalse(lastInForeground.isModerateBindingBound()); | |
488 ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); | |
489 for (TestChildProcessConnection connection : connections) { | |
490 Assert.assertFalse(connection.isModerateBindingBound()); | |
491 } | |
492 | |
493 // Call onBroughtToForeground() and verify that the previous moderate bi
ndings aren't | |
494 // recovered. | |
495 manager.onBroughtToForeground(); | |
496 for (TestChildProcessConnection connection : connections) { | |
497 Assert.assertFalse(connection.isModerateBindingBound()); | |
498 } | |
499 } | |
500 | |
501 /** | |
502 * Verifies that onLowMemory() drops all the moderate bindings. | |
503 */ | |
504 @Test | |
505 @Feature({"ProcessManagement"}) | |
506 public void testModerateBindingDropOnLowMemory() { | |
507 final Application app = mActivity.getApplication(); | |
508 final BindingManagerImpl manager = mModerateBindingManager; | |
509 | |
510 TestChildProcessConnection[] connections = new TestChildProcessConnectio
n[4]; | |
511 for (int i = 0; i < connections.length; i++) { | |
512 connections[i] = new TestChildProcessConnection(i + 1); | |
513 connections[i].start(null /* startCallback */); | |
514 manager.addNewConnection(connections[i].getPid(), connections[i]); | |
515 } | |
516 | |
517 // Verify that each connection has a moderate binding after binding and
releasing a strong | |
518 // binding. | |
519 for (TestChildProcessConnection connection : connections) { | |
520 manager.setInForeground(connection.getPid(), true); | |
521 manager.setInForeground(connection.getPid(), false); | |
522 ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); | |
523 Assert.assertTrue(connection.isModerateBindingBound()); | |
524 } | |
525 | |
526 // Call onLowMemory() and verify that all the moderate bindings drop. | |
527 app.onLowMemory(); | |
528 for (TestChildProcessConnection connection : connections) { | |
529 Assert.assertFalse(connection.isModerateBindingBound()); | |
530 } | |
531 } | |
532 | |
533 /** | |
534 * Verifies that onTrimMemory() drops moderate bindings properly. | |
535 */ | |
536 @Test | |
537 @Feature({"ProcessManagement"}) | |
538 public void testModerateBindingDropOnTrimMemory() { | |
539 final Application app = mActivity.getApplication(); | |
540 // This test applies only to the moderate-binding manager. | |
541 final BindingManagerImpl manager = mModerateBindingManager; | |
542 | |
543 ArrayList<Pair<Integer, Integer>> levelAndExpectedVictimCountList = new
ArrayList<>(); | |
544 levelAndExpectedVictimCountList.add( | |
545 new Pair<Integer, Integer>(TRIM_MEMORY_RUNNING_MODERATE, 1)); | |
546 levelAndExpectedVictimCountList.add(new Pair<Integer, Integer>(TRIM_MEMO
RY_RUNNING_LOW, 2)); | |
547 levelAndExpectedVictimCountList.add( | |
548 new Pair<Integer, Integer>(TRIM_MEMORY_RUNNING_CRITICAL, 4)); | |
549 | |
550 TestChildProcessConnection[] connections = new TestChildProcessConnectio
n[4]; | |
551 for (int i = 0; i < connections.length; i++) { | |
552 connections[i] = new TestChildProcessConnection(i + 1); | |
553 connections[i].start(null /* startCallback */); | |
554 manager.addNewConnection(connections[i].getPid(), connections[i]); | |
555 } | |
556 | |
557 for (Pair<Integer, Integer> pair : levelAndExpectedVictimCountList) { | |
558 String message = "Failed for the level=" + pair.first; | |
559 // Verify that each connection has a moderate binding after binding
and releasing a | |
560 // strong binding. | |
561 for (TestChildProcessConnection connection : connections) { | |
562 manager.setInForeground(connection.getPid(), true); | |
563 manager.setInForeground(connection.getPid(), false); | |
564 ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); | |
565 Assert.assertTrue(message, connection.isModerateBindingBound()); | |
566 } | |
567 | |
568 app.onTrimMemory(pair.first); | |
569 // Verify that some of moderate bindings drop. | |
570 for (int i = 0; i < connections.length; i++) { | |
571 Assert.assertEquals( | |
572 message, i >= pair.second, connections[i].isModerateBind
ingBound()); | |
573 } | |
574 } | |
575 } | |
576 | |
577 /** | |
578 * Verifies that BindingManager.releaseAllModerateBindings() drops all the m
oderate bindings. | |
579 */ | |
580 @Test | |
581 @Feature({"ProcessManagement"}) | |
582 public void testModerateBindingDropOnReleaseAllModerateBindings() { | |
583 // This test applies only to the moderate-binding manager. | |
584 final BindingManagerImpl manager = mModerateBindingManager; | |
585 | |
586 TestChildProcessConnection[] connections = new TestChildProcessConnectio
n[4]; | |
587 for (int i = 0; i < connections.length; i++) { | |
588 connections[i] = new TestChildProcessConnection(i + 1); | |
589 connections[i].start(null /* startCallback */); | |
590 manager.addNewConnection(connections[i].getPid(), connections[i]); | |
591 } | |
592 | |
593 // Verify that each connection has a moderate binding after binding and
releasing a strong | |
594 // binding. | |
595 for (TestChildProcessConnection connection : connections) { | |
596 manager.setInForeground(connection.getPid(), true); | |
597 manager.setInForeground(connection.getPid(), false); | |
598 ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); | |
599 Assert.assertTrue(connection.isModerateBindingBound()); | |
600 } | |
601 | |
602 // Call BindingManager.releaseAllModerateBindings() and verify that all
the moderate | |
603 // bindings drop. | |
604 manager.releaseAllModerateBindings(); | |
605 for (TestChildProcessConnection connection : connections) { | |
606 Assert.assertFalse(connection.isModerateBindingBound()); | |
607 } | |
608 } | |
609 | |
610 /* | |
611 * Test that a moderate binding is added to background renderer processes wh
en the initial | |
612 * binding is removed. | |
613 */ | |
614 @Test | |
615 @Feature({"ProcessManagement"}) | |
616 public void testModerateBindingTillBackgroundedBackgroundProcess() { | |
617 BindingManagerImpl manager = BindingManagerImpl.createBindingManagerForT
esting(false); | |
618 manager.startModerateBindingManagement(mActivity, 4); | |
619 | |
620 TestChildProcessConnection connection = new TestChildProcessConnection(0
); | |
621 connection.start(null /* startCallback */); | |
622 manager.addNewConnection(connection.getPid(), connection); | |
623 Assert.assertTrue(connection.isInitialBindingBound()); | |
624 Assert.assertFalse(connection.isModerateBindingBound()); | |
625 | |
626 manager.setInForeground(connection.getPid(), false); | |
627 manager.onDeterminedVisibility(connection.getPid()); | |
628 Assert.assertFalse(connection.isInitialBindingBound()); | |
629 Assert.assertTrue(connection.isModerateBindingBound()); | |
630 } | |
631 | |
632 /* | |
633 * Test that a moderate binding is not added to foreground renderer processe
s when the initial | |
634 * binding is removed. | |
635 */ | |
636 @Test | |
637 @Feature({"ProcessManagement"}) | |
638 public void testModerateBindingTillBackgroundedForegroundProcess() { | |
639 BindingManagerImpl manager = BindingManagerImpl.createBindingManagerForT
esting(false); | |
640 manager.startModerateBindingManagement(mActivity, 4); | |
641 | |
642 TestChildProcessConnection connection = new TestChildProcessConnection(0
); | |
643 connection.start(null /* startCallback */); | |
644 manager.addNewConnection(connection.getPid(), connection); | |
645 Assert.assertTrue(connection.isInitialBindingBound()); | |
646 Assert.assertFalse(connection.isStrongBindingBound()); | |
647 Assert.assertFalse(connection.isModerateBindingBound()); | |
648 | |
649 manager.setInForeground(connection.getPid(), true); | |
650 manager.onDeterminedVisibility(connection.getPid()); | |
651 Assert.assertFalse(connection.isInitialBindingBound()); | |
652 Assert.assertTrue(connection.isStrongBindingBound()); | |
653 Assert.assertFalse(connection.isModerateBindingBound()); | |
654 } | |
655 | |
656 /* | |
657 * Test that Chrome is sent to the background, that the initially added mode
rate bindings are | |
658 * removed and are not re-added when Chrome is brought back to the foregroun
d. | |
659 */ | |
660 @Test | |
661 @Feature({"ProcessManagement"}) | |
662 public void testModerateBindingTillBackgroundedSentToBackground() { | |
663 BindingManagerImpl manager = BindingManagerImpl.createBindingManagerForT
esting(false); | |
664 manager.startModerateBindingManagement(mActivity, 4); | |
665 | |
666 TestChildProcessConnection connection = new TestChildProcessConnection(0
); | |
667 connection.start(null /* startCallback */); | |
668 manager.addNewConnection(connection.getPid(), connection); | |
669 manager.setInForeground(connection.getPid(), false); | |
670 manager.onDeterminedVisibility(connection.getPid()); | |
671 Assert.assertTrue(connection.isModerateBindingBound()); | |
672 | |
673 manager.onSentToBackground(); | |
674 ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); | |
675 Assert.assertFalse(connection.isModerateBindingBound()); | |
676 | |
677 // Bringing Chrome to the foreground should not re-add the moderate bind
ings. | |
678 manager.onBroughtToForeground(); | |
679 Assert.assertFalse(connection.isModerateBindingBound()); | |
680 } | |
681 } | |
OLD | NEW |