| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.content.browser; | 5 package org.chromium.content.browser; |
| 6 | 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.Application; |
| 7 import android.os.Bundle; | 12 import android.os.Bundle; |
| 8 import android.test.InstrumentationTestCase; | 13 import android.test.InstrumentationTestCase; |
| 9 import android.test.suitebuilder.annotation.SmallTest; | 14 import android.test.suitebuilder.annotation.SmallTest; |
| 15 import android.util.Pair; |
| 10 | 16 |
| 11 import org.chromium.base.test.util.Feature; | 17 import org.chromium.base.test.util.Feature; |
| 12 import org.chromium.content.common.IChildProcessCallback; | 18 import org.chromium.content.common.IChildProcessCallback; |
| 13 import org.chromium.content.common.IChildProcessService; | 19 import org.chromium.content.common.IChildProcessService; |
| 14 | 20 |
| 21 import java.util.ArrayList; |
| 22 |
| 15 /** | 23 /** |
| 16 * Unit tests for BindingManagerImpl. The tests run agains mock ChildProcessConn
ection | 24 * Unit tests for BindingManagerImpl. The tests run agains mock ChildProcessConn
ection |
| 17 * implementation, thus testing only the BindingManagerImpl itself. | 25 * implementation, thus testing only the BindingManagerImpl itself. |
| 18 * | 26 * |
| 19 * Default property of being low-end device is overriden, so that both low-end a
nd high-end policies | 27 * Default property of being low-end device is overriden, so that both low-end a
nd high-end policies |
| 20 * are tested. Unbinding delays are set to 0, so that we don't need to deal with
waiting, but we | 28 * are tested. Unbinding delays are set to 0, so that we don't need to deal with
waiting, but we |
| 21 * still can test if the unbinding tasks are posted or executed synchronously. | 29 * still can test if the unbinding tasks are posted or executed synchronously. |
| 22 */ | 30 */ |
| 23 public class BindingManagerImplTest extends InstrumentationTestCase { | 31 public class BindingManagerImplTest extends InstrumentationTestCase { |
| 24 private static class MockChildProcessConnection implements ChildProcessConne
ction { | 32 private static class MockChildProcessConnection implements ChildProcessConne
ction { |
| 25 boolean mInitialBindingBound; | 33 boolean mInitialBindingBound; |
| 34 boolean mModerateBindingBound; |
| 26 int mStrongBindingCount; | 35 int mStrongBindingCount; |
| 27 final int mPid; | 36 final int mPid; |
| 28 | 37 |
| 29 /** | 38 /** |
| 30 * Creates a mock binding corresponding to real ChildProcessConnectionIm
pl after the | 39 * Creates a mock binding corresponding to real ChildProcessConnectionIm
pl after the |
| 31 * connection is established: with initial binding bound and no strong b
inding. | 40 * connection is established: with initial binding bound and no strong b
inding. |
| 32 */ | 41 */ |
| 33 MockChildProcessConnection(int pid) { | 42 MockChildProcessConnection(int pid) { |
| 34 mInitialBindingBound = true; | 43 mInitialBindingBound = true; |
| 35 mStrongBindingCount = 0; | 44 mStrongBindingCount = 0; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 79 } | 88 } |
| 80 | 89 |
| 81 @Override | 90 @Override |
| 82 public void stop() { | 91 public void stop() { |
| 83 mInitialBindingBound = false; | 92 mInitialBindingBound = false; |
| 84 mStrongBindingCount = 0; | 93 mStrongBindingCount = 0; |
| 85 } | 94 } |
| 86 | 95 |
| 87 @Override | 96 @Override |
| 88 public int getServiceNumber() { | 97 public int getServiceNumber() { |
| 89 throw new UnsupportedOperationException(); | 98 return mPid; |
| 90 } | 99 } |
| 91 | 100 |
| 92 @Override | 101 @Override |
| 93 public boolean isInSandbox() { | 102 public boolean isInSandbox() { |
| 94 throw new UnsupportedOperationException(); | 103 return true; |
| 95 } | 104 } |
| 96 | 105 |
| 97 @Override | 106 @Override |
| 98 public IChildProcessService getService() { | 107 public IChildProcessService getService() { |
| 99 throw new UnsupportedOperationException(); | 108 throw new UnsupportedOperationException(); |
| 100 } | 109 } |
| 101 | 110 |
| 102 @Override | 111 @Override |
| 103 public void start(String[] commandLine) { | 112 public void start(String[] commandLine) { |
| 104 throw new UnsupportedOperationException(); | 113 throw new UnsupportedOperationException(); |
| 105 } | 114 } |
| 106 | 115 |
| 107 @Override | 116 @Override |
| 108 public void setupConnection(String[] commandLine, FileDescriptorInfo[] f
ilesToBeMapped, | 117 public void setupConnection(String[] commandLine, FileDescriptorInfo[] f
ilesToBeMapped, |
| 109 IChildProcessCallback processCallback, ConnectionCallback connec
tionCallbacks, | 118 IChildProcessCallback processCallback, ConnectionCallback connec
tionCallbacks, |
| 110 Bundle sharedRelros) { | 119 Bundle sharedRelros) { |
| 111 throw new UnsupportedOperationException(); | 120 throw new UnsupportedOperationException(); |
| 112 } | 121 } |
| 122 |
| 123 @Override |
| 124 public void addModerateBinding() { |
| 125 mModerateBindingBound = true; |
| 126 } |
| 127 |
| 128 @Override |
| 129 public void removeModerateBinding() { |
| 130 mModerateBindingBound = false; |
| 131 } |
| 132 |
| 133 @Override |
| 134 public boolean isModerateBindingBound() { |
| 135 return mModerateBindingBound; |
| 136 } |
| 113 } | 137 } |
| 114 | 138 |
| 115 /** | 139 /** |
| 116 * Helper class that stores a manager along with its text label. This is use
d for tests that | 140 * Helper class that stores a manager along with its text label. This is use
d for tests that |
| 117 * iterate over all managers to indicate which manager was being tested when
an assertion | 141 * iterate over all managers to indicate which manager was being tested when
an assertion |
| 118 * failed. | 142 * failed. |
| 119 */ | 143 */ |
| 120 private static class ManagerEntry { | 144 private static class ManagerEntry { |
| 121 BindingManagerImpl mManager; | 145 BindingManagerImpl mManager; |
| 122 String mLabel; // Name of the manager. | 146 String mLabel; // Name of the manager. |
| 123 | 147 |
| 124 ManagerEntry(BindingManagerImpl manager, String label) { | 148 ManagerEntry(BindingManagerImpl manager, String label) { |
| 125 mManager = manager; | 149 mManager = manager; |
| 126 mLabel = label; | 150 mLabel = label; |
| 127 } | 151 } |
| 128 | 152 |
| 129 String getErrorMessage() { | 153 String getErrorMessage() { |
| 130 return "Failed for the " + mLabel + " manager."; | 154 return "Failed for the " + mLabel + " manager."; |
| 131 } | 155 } |
| 132 } | 156 } |
| 133 | 157 |
| 134 // The managers are created in setUp() for convenience. | 158 // The managers are created in setUp() for convenience. |
| 135 BindingManagerImpl mLowEndManager; | 159 BindingManagerImpl mLowEndManager; |
| 136 BindingManagerImpl mHighEndManager; | 160 BindingManagerImpl mHighEndManager; |
| 161 BindingManagerImpl mModerateBindingManager; |
| 137 ManagerEntry[] mAllManagers; | 162 ManagerEntry[] mAllManagers; |
| 138 | 163 |
| 139 @Override | 164 @Override |
| 140 protected void setUp() { | 165 protected void setUp() { |
| 141 mLowEndManager = BindingManagerImpl.createBindingManagerForTesting(true)
; | 166 mLowEndManager = BindingManagerImpl.createBindingManagerForTesting(true)
; |
| 142 mHighEndManager = BindingManagerImpl.createBindingManagerForTesting(fals
e); | 167 mHighEndManager = BindingManagerImpl.createBindingManagerForTesting(fals
e); |
| 168 mModerateBindingManager = BindingManagerImpl.createBindingManagerForTest
ing(false); |
| 169 mModerateBindingManager.startModerateBindingManagement( |
| 170 getInstrumentation().getTargetContext(), 4, 0.25f, 0.5f); |
| 143 mAllManagers = new ManagerEntry[] { | 171 mAllManagers = new ManagerEntry[] { |
| 144 new ManagerEntry(mLowEndManager, "low-end"), | 172 new ManagerEntry(mLowEndManager, "low-end"), |
| 145 new ManagerEntry(mHighEndManager, "high-end")}; | 173 new ManagerEntry(mHighEndManager, "high-end"), |
| 174 new ManagerEntry(mModerateBindingManager, "moderate-binding")}; |
| 146 } | 175 } |
| 147 | 176 |
| 148 /** | 177 /** |
| 149 * Verifies that when running on low-end, the binding manager drops the oom
bindings for the | 178 * Verifies that when running on low-end, the binding manager drops the oom
bindings for the |
| 150 * previously bound connection when a new connection is used in foreground. | 179 * previously bound connection when a new connection is used in foreground. |
| 151 */ | 180 */ |
| 152 @SmallTest | 181 @SmallTest |
| 153 @Feature({"ProcessManagement"}) | 182 @Feature({"ProcessManagement"}) |
| 154 public void testNewConnectionDropsPreviousOnLowEnd() { | 183 public void testNewConnectionDropsPreviousOnLowEnd() { |
| 155 // This test applies only to the low-end manager. | 184 // This test applies only to the low-end manager. |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 247 | 276 |
| 248 // Wait until the posted unbinding tasks get executed and verify that th
e strong binding was | 277 // Wait until the posted unbinding tasks get executed and verify that th
e strong binding was |
| 249 // removed while the initial binding is not affected. Note that this wor
ks only because the | 278 // removed while the initial binding is not affected. Note that this wor
ks only because the |
| 250 // test binding manager has the unbinding delay set to 0. | 279 // test binding manager has the unbinding delay set to 0. |
| 251 getInstrumentation().waitForIdleSync(); | 280 getInstrumentation().waitForIdleSync(); |
| 252 assertFalse(connection.isStrongBindingBound()); | 281 assertFalse(connection.isStrongBindingBound()); |
| 253 assertTrue(connection.isInitialBindingBound()); | 282 assertTrue(connection.isInitialBindingBound()); |
| 254 } | 283 } |
| 255 | 284 |
| 256 /** | 285 /** |
| 286 * Verifies the strong binding removal policies with moderate binding manage
ment, where the |
| 287 * moderate binding should be bound. |
| 288 */ |
| 289 @SmallTest |
| 290 @Feature({"ProcessManagement"}) |
| 291 public void testStrongBindingRemovalWithModerateBinding() throws Throwable { |
| 292 // This test applies only to the moderate-binding manager. |
| 293 final BindingManagerImpl manager = mModerateBindingManager; |
| 294 |
| 295 // Add a connection to the manager. |
| 296 final MockChildProcessConnection connection = new MockChildProcessConnec
tion(1); |
| 297 manager.addNewConnection(connection.getPid(), connection); |
| 298 assertTrue(connection.isInitialBindingBound()); |
| 299 assertFalse(connection.isStrongBindingBound()); |
| 300 assertFalse(connection.isModerateBindingBound()); |
| 301 // This has to happen on the UI thread, so that we can check the binding
status right after |
| 302 // the call to remove it, before the any other task is executed on the m
ain thread. |
| 303 runTestOnUiThread(new Runnable() { |
| 304 @Override |
| 305 public void run() { |
| 306 // Add a strong binding, verify that the initial binding is not
removed. |
| 307 manager.setInForeground(connection.getPid(), true); |
| 308 assertTrue(connection.isStrongBindingBound()); |
| 309 assertTrue(connection.isInitialBindingBound()); |
| 310 assertFalse(connection.isModerateBindingBound()); |
| 311 |
| 312 // Remove the strong binding, verify that the strong binding is
not removed |
| 313 // immediately. |
| 314 manager.setInForeground(connection.getPid(), false); |
| 315 assertTrue(connection.isStrongBindingBound()); |
| 316 assertTrue(connection.isInitialBindingBound()); |
| 317 assertFalse(connection.isModerateBindingBound()); |
| 318 } |
| 319 }); |
| 320 |
| 321 // Wait until the posted unbinding tasks get executed and verify that th
e strong binding was |
| 322 // removed while the initial binding is not affected, and the moderate b
inding is bound. |
| 323 getInstrumentation().waitForIdleSync(); |
| 324 assertFalse(connection.isStrongBindingBound()); |
| 325 assertTrue(connection.isInitialBindingBound()); |
| 326 assertTrue(connection.isModerateBindingBound()); |
| 327 } |
| 328 |
| 329 /** |
| 257 * Verifies that the initial binding is removed after determinedVisibility()
is called. | 330 * Verifies that the initial binding is removed after determinedVisibility()
is called. |
| 258 */ | 331 */ |
| 259 @SmallTest | 332 @SmallTest |
| 260 @Feature({"ProcessManagement"}) | 333 @Feature({"ProcessManagement"}) |
| 261 public void testInitialBindingRemoval() { | 334 public void testInitialBindingRemoval() { |
| 262 // This test applies to both low-end and high-end policies. | 335 // This test applies to low-end, high-end and moderate-binding policies. |
| 263 for (ManagerEntry managerEntry : mAllManagers) { | 336 for (ManagerEntry managerEntry : mAllManagers) { |
| 264 BindingManagerImpl manager = managerEntry.mManager; | 337 BindingManagerImpl manager = managerEntry.mManager; |
| 265 String message = managerEntry.getErrorMessage(); | 338 String message = managerEntry.getErrorMessage(); |
| 266 | 339 |
| 267 // Add a connection to the manager. | 340 // Add a connection to the manager. |
| 268 MockChildProcessConnection connection = new MockChildProcessConnecti
on(1); | 341 MockChildProcessConnection connection = new MockChildProcessConnecti
on(1); |
| 269 manager.addNewConnection(connection.getPid(), connection); | 342 manager.addNewConnection(connection.getPid(), connection); |
| 270 | 343 |
| 271 // Verify that the initial binding is held. | 344 // Verify that the initial binding is held. |
| 272 assertTrue(connection.isInitialBindingBound()); | 345 assertTrue(connection.isInitialBindingBound()); |
| 273 | 346 |
| 274 // Call determinedVisibility() and verify that the initial binding w
as released. | 347 // Call determinedVisibility() and verify that the initial binding w
as released. |
| 275 manager.determinedVisibility(connection.getPid()); | 348 manager.determinedVisibility(connection.getPid()); |
| 276 assertFalse(connection.isInitialBindingBound()); | 349 assertFalse(connection.isInitialBindingBound()); |
| 277 } | 350 } |
| 278 } | 351 } |
| 279 | 352 |
| 280 /** | 353 /** |
| 281 * Verifies that BindingManagerImpl correctly stashes the status of the conn
ection oom bindings | 354 * Verifies that BindingManagerImpl correctly stashes the status of the conn
ection oom bindings |
| 282 * when the connection is cleared. BindingManagerImpl should reply to isOomP
rotected() queries | 355 * when the connection is cleared. BindingManagerImpl should reply to isOomP
rotected() queries |
| 283 * with live status of the connection while it's still around and reply with
stashed status | 356 * with live status of the connection while it's still around and reply with
stashed status |
| 284 * after clearConnection() is called. | 357 * after clearConnection() is called. |
| 285 * | 358 * |
| 286 * This test corresponds to a process crash scenario: after a process dies a
nd its connection is | 359 * This test corresponds to a process crash scenario: after a process dies a
nd its connection is |
| 287 * cleared, isOomProtected() may be called to decide if it was a crash or ou
t-of-memory kill. | 360 * cleared, isOomProtected() may be called to decide if it was a crash or ou
t-of-memory kill. |
| 288 */ | 361 */ |
| 289 @SmallTest | 362 @SmallTest |
| 290 @Feature({"ProcessManagement"}) | 363 @Feature({"ProcessManagement"}) |
| 291 public void testIsOomProtected() { | 364 public void testIsOomProtected() { |
| 292 // This test applies to both low-end and high-end policies. | 365 // This test applies to low-end, high-end and moderate-binding policies. |
| 293 for (ManagerEntry managerEntry : mAllManagers) { | 366 for (ManagerEntry managerEntry : mAllManagers) { |
| 294 BindingManagerImpl manager = managerEntry.mManager; | 367 BindingManagerImpl manager = managerEntry.mManager; |
| 295 String message = managerEntry.getErrorMessage(); | 368 String message = managerEntry.getErrorMessage(); |
| 296 | 369 |
| 297 // Add a connection to the manager. | 370 // Add a connection to the manager. |
| 298 MockChildProcessConnection connection = new MockChildProcessConnecti
on(1); | 371 MockChildProcessConnection connection = new MockChildProcessConnecti
on(1); |
| 299 manager.addNewConnection(connection.getPid(), connection); | 372 manager.addNewConnection(connection.getPid(), connection); |
| 300 | 373 |
| 301 // Initial binding is an oom binding. | 374 // Initial binding is an oom binding. |
| 302 assertTrue(message, manager.isOomProtected(connection.getPid())); | 375 assertTrue(message, manager.isOomProtected(connection.getPid())); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 332 * period. | 405 * period. |
| 333 * | 406 * |
| 334 * The renderer that will be bound for the background period should be the o
ne that was most | 407 * The renderer that will be bound for the background period should be the o
ne that was most |
| 335 * recendly bound using .setInForeground(), even if there is one that was ad
ded using | 408 * recendly bound using .setInForeground(), even if there is one that was ad
ded using |
| 336 * .addNewConnection() after that. Otherwise we would bound a background ren
derer when user | 409 * .addNewConnection() after that. Otherwise we would bound a background ren
derer when user |
| 337 * loads a new tab in background and leaves the browser. | 410 * loads a new tab in background and leaves the browser. |
| 338 */ | 411 */ |
| 339 @SmallTest | 412 @SmallTest |
| 340 @Feature({"ProcessManagement"}) | 413 @Feature({"ProcessManagement"}) |
| 341 public void testBackgroundPeriodBinding() { | 414 public void testBackgroundPeriodBinding() { |
| 342 // This test applies to both low-end and high-end policies. | 415 // This test applies to low-end, high-end and moderate-binding policies. |
| 343 for (ManagerEntry managerEntry : mAllManagers) { | 416 for (ManagerEntry managerEntry : mAllManagers) { |
| 344 BindingManagerImpl manager = managerEntry.mManager; | 417 BindingManagerImpl manager = managerEntry.mManager; |
| 345 String message = managerEntry.getErrorMessage(); | 418 String message = managerEntry.getErrorMessage(); |
| 346 | 419 |
| 347 // Add two connections, bind and release each. | 420 // Add two connections, bind and release each. |
| 348 MockChildProcessConnection firstConnection = new MockChildProcessCon
nection(1); | 421 MockChildProcessConnection firstConnection = new MockChildProcessCon
nection(1); |
| 349 manager.addNewConnection(firstConnection.getPid(), firstConnection); | 422 manager.addNewConnection(firstConnection.getPid(), firstConnection); |
| 350 manager.setInForeground(firstConnection.getPid(), true); | 423 manager.setInForeground(firstConnection.getPid(), true); |
| 351 manager.setInForeground(firstConnection.getPid(), false); | 424 manager.setInForeground(firstConnection.getPid(), false); |
| 352 | 425 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 376 assertFalse(message, thirdConnection.isStrongBindingBound()); | 449 assertFalse(message, thirdConnection.isStrongBindingBound()); |
| 377 | 450 |
| 378 // Call onBroughtToForeground() and verify that the strong binding w
as removed. | 451 // Call onBroughtToForeground() and verify that the strong binding w
as removed. |
| 379 manager.onBroughtToForeground(); | 452 manager.onBroughtToForeground(); |
| 380 getInstrumentation().waitForIdleSync(); | 453 getInstrumentation().waitForIdleSync(); |
| 381 assertFalse(message, firstConnection.isStrongBindingBound()); | 454 assertFalse(message, firstConnection.isStrongBindingBound()); |
| 382 assertFalse(message, secondConnection.isStrongBindingBound()); | 455 assertFalse(message, secondConnection.isStrongBindingBound()); |
| 383 assertFalse(message, thirdConnection.isStrongBindingBound()); | 456 assertFalse(message, thirdConnection.isStrongBindingBound()); |
| 384 } | 457 } |
| 385 } | 458 } |
| 459 |
| 460 /** |
| 461 * Verifies that onSentToBackground() drops all the moderate bindings, and |
| 462 * onBroughtToForeground() doesn't recover them. |
| 463 */ |
| 464 @SmallTest |
| 465 @Feature({"ProcessManagement"}) |
| 466 public void testModerateBindingDropOnBackground() { |
| 467 // This test applies only to the moderate-binding manager. |
| 468 final BindingManagerImpl manager = mModerateBindingManager; |
| 469 |
| 470 MockChildProcessConnection[] connections = new MockChildProcessConnectio
n[4]; |
| 471 for (int i = 0; i < connections.length; i++) { |
| 472 connections[i] = new MockChildProcessConnection(i + 1); |
| 473 manager.addNewConnection(connections[i].getPid(), connections[i]); |
| 474 } |
| 475 |
| 476 // Verify that each connection has a moderate binding after binding and
releasing a strong |
| 477 // binding. |
| 478 for (MockChildProcessConnection connection : connections) { |
| 479 manager.setInForeground(connection.getPid(), true); |
| 480 manager.setInForeground(connection.getPid(), false); |
| 481 getInstrumentation().waitForIdleSync(); |
| 482 assertTrue(connection.isModerateBindingBound()); |
| 483 } |
| 484 |
| 485 // Call onSentToBackground() and verify that all the moderate bindings d
rop. |
| 486 manager.onSentToBackground(); |
| 487 for (MockChildProcessConnection connection : connections) { |
| 488 assertFalse(connection.isModerateBindingBound()); |
| 489 } |
| 490 |
| 491 // Call onBroughtToForeground() and verify that the previous moderate bi
ndings aren't |
| 492 // recovered. |
| 493 manager.onBroughtToForeground(); |
| 494 for (MockChildProcessConnection connection : connections) { |
| 495 assertFalse(connection.isModerateBindingBound()); |
| 496 } |
| 497 } |
| 498 |
| 499 /** |
| 500 * Verifies that onLowMemory() drops all the moderate bindings. |
| 501 */ |
| 502 @SmallTest |
| 503 @Feature({"ProcessManagement"}) |
| 504 public void testModerateBindingDropOnLowMemory() { |
| 505 final Application app = |
| 506 (Application) getInstrumentation().getTargetContext().getApplica
tionContext(); |
| 507 // This test applies only to the moderate-binding manager. |
| 508 final BindingManagerImpl manager = mModerateBindingManager; |
| 509 |
| 510 MockChildProcessConnection[] connections = new MockChildProcessConnectio
n[4]; |
| 511 for (int i = 0; i < connections.length; i++) { |
| 512 connections[i] = new MockChildProcessConnection(i + 1); |
| 513 manager.addNewConnection(connections[i].getPid(), connections[i]); |
| 514 } |
| 515 |
| 516 // Verify that each connection has a moderate binding after binding and
releasing a strong |
| 517 // binding. |
| 518 for (MockChildProcessConnection connection : connections) { |
| 519 manager.setInForeground(connection.getPid(), true); |
| 520 manager.setInForeground(connection.getPid(), false); |
| 521 getInstrumentation().waitForIdleSync(); |
| 522 assertTrue(connection.isModerateBindingBound()); |
| 523 } |
| 524 |
| 525 // Call onLowMemory() and verify that all the moderate bindings drop. |
| 526 app.onLowMemory(); |
| 527 for (MockChildProcessConnection connection : connections) { |
| 528 assertFalse(connection.isModerateBindingBound()); |
| 529 } |
| 530 } |
| 531 |
| 532 /** |
| 533 * Verifies that onTrimMemory() drops moderate bindings properly. |
| 534 */ |
| 535 @SmallTest |
| 536 @Feature({"ProcessManagement"}) |
| 537 public void testModerateBindingDropOnTrimMemory() { |
| 538 final Application app = |
| 539 (Application) getInstrumentation().getTargetContext().getApplica
tionContext(); |
| 540 // This test applies only to the moderate-binding manager. |
| 541 final BindingManagerImpl manager = mModerateBindingManager; |
| 542 |
| 543 ArrayList<Pair<Integer, Integer>> levelAndExpectedVictimCountList = |
| 544 new ArrayList<Pair<Integer, Integer>>(); |
| 545 levelAndExpectedVictimCountList.add( |
| 546 new Pair<Integer, Integer>(TRIM_MEMORY_RUNNING_MODERATE, 1)); |
| 547 levelAndExpectedVictimCountList.add(new Pair<Integer, Integer>(TRIM_MEMO
RY_RUNNING_LOW, 2)); |
| 548 levelAndExpectedVictimCountList.add( |
| 549 new Pair<Integer, Integer>(TRIM_MEMORY_RUNNING_CRITICAL, 4)); |
| 550 |
| 551 MockChildProcessConnection[] connections = new MockChildProcessConnectio
n[4]; |
| 552 for (int i = 0; i < connections.length; i++) { |
| 553 connections[i] = new MockChildProcessConnection(i + 1); |
| 554 manager.addNewConnection(connections[i].getPid(), connections[i]); |
| 555 } |
| 556 |
| 557 for (Pair<Integer, Integer> pair : levelAndExpectedVictimCountList) { |
| 558 String message = String.format("Failed for the level=%d", pair.first
); |
| 559 // Verify that each connection has a moderate binding after binding
and releasing a |
| 560 // strong binding. |
| 561 for (MockChildProcessConnection connection : connections) { |
| 562 manager.setInForeground(connection.getPid(), true); |
| 563 manager.setInForeground(connection.getPid(), false); |
| 564 getInstrumentation().waitForIdleSync(); |
| 565 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 assertEquals(message, i >= pair.second, connections[i].isModerat
eBindingBound()); |
| 572 } |
| 573 } |
| 574 } |
| 386 } | 575 } |
| OLD | NEW |