Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(404)

Side by Side Diff: base/android/java/src/org/chromium/base/process_launcher/BindingManagerImpl.java

Issue 2845243002: Moving BindingManager and ChildProcessConnection to base/.
Patch Set: Moving BindingManager and ChildProcessConnection to base/. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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.base.process_launcher;
6 6
7 import android.annotation.TargetApi; 7 import android.annotation.TargetApi;
8 import android.content.ComponentCallbacks2; 8 import android.content.ComponentCallbacks2;
9 import android.content.Context; 9 import android.content.Context;
10 import android.content.res.Configuration; 10 import android.content.res.Configuration;
11 import android.os.Build; 11 import android.os.Build;
12 import android.os.Handler;
13 import android.os.Looper;
12 import android.util.LruCache; 14 import android.util.LruCache;
13 import android.util.SparseArray; 15 import android.util.SparseArray;
14 16
15 import org.chromium.base.Log; 17 import org.chromium.base.Log;
16 import org.chromium.base.SysUtils; 18 import org.chromium.base.SysUtils;
17 import org.chromium.base.ThreadUtils; 19 import org.chromium.base.ThreadUtils;
18 import org.chromium.base.VisibleForTesting; 20 import org.chromium.base.VisibleForTesting;
19 import org.chromium.base.metrics.RecordHistogram; 21 import org.chromium.base.metrics.RecordHistogram;
20 22
21 import java.util.Map; 23 import java.util.Map;
22 24
23 /** 25 /**
24 * Manages oom bindings used to bound child services. 26 * Manages oom bindings used to bound child services.
25 * This object must only be accessed from the launcher thread. 27 * This object must only be accessed from the launcher thread.
26 */ 28 */
27 class BindingManagerImpl implements BindingManager { 29 public class BindingManagerImpl implements BindingManager {
28 private static final String TAG = "cr.BindingManager"; 30 private static final String TAG = "cr_BindingManager";
29 31
30 // Low reduce ratio of moderate binding. 32 // Low reduce ratio of moderate binding.
31 private static final float MODERATE_BINDING_LOW_REDUCE_RATIO = 0.25f; 33 private static final float MODERATE_BINDING_LOW_REDUCE_RATIO = 0.25f;
32 // High reduce ratio of moderate binding. 34 // High reduce ratio of moderate binding.
33 private static final float MODERATE_BINDING_HIGH_REDUCE_RATIO = 0.5f; 35 private static final float MODERATE_BINDING_HIGH_REDUCE_RATIO = 0.5f;
34 36
35 // Delay of 1 second used when removing temporary strong binding of a proces s (only on 37 // Delay of 1 second used when removing temporary strong binding of a proces s (only on
36 // non-low-memory devices). 38 // non-low-memory devices).
37 private static final long DETACH_AS_ACTIVE_HIGH_END_DELAY_MILLIS = 1 * 1000; 39 private static final long DETACH_AS_ACTIVE_HIGH_END_DELAY_MILLIS = 1 * 1000;
38 40
39 // Delays used when clearing moderate binding pool when onSentToBackground h appens. 41 // Delays used when clearing moderate binding pool when onSentToBackground h appens.
40 private static final long MODERATE_BINDING_POOL_CLEARER_DELAY_MILLIS = 10 * 1000; 42 private static final long MODERATE_BINDING_POOL_CLEARER_DELAY_MILLIS = 10 * 1000;
41 43
44 // The handler for the thread this BindingManager should be accessed on.
45 private final Handler mHandler;
46
42 // These fields allow to override the parameters for testing - see 47 // These fields allow to override the parameters for testing - see
43 // createBindingManagerForTesting(). 48 // createBindingManagerForTesting().
44 private final boolean mIsLowMemoryDevice; 49 private final boolean mIsLowMemoryDevice;
45 50
46 private static class ModerateBindingPool 51 private class ModerateBindingPool
47 extends LruCache<Integer, ManagedConnection> implements ComponentCal lbacks2 { 52 extends LruCache<Integer, ManagedConnection> implements ComponentCal lbacks2 {
48 private Runnable mDelayedClearer; 53 private Runnable mDelayedClearer;
49 54
50 public ModerateBindingPool(int maxSize) { 55 public ModerateBindingPool(int maxSize) {
51 super(maxSize); 56 super(maxSize);
52 } 57 }
53 58
54 @Override 59 @Override
55 public void onTrimMemory(final int level) { 60 public void onTrimMemory(final int level) {
56 ThreadUtils.assertOnUiThread(); 61 ThreadUtils.assertOnUiThread();
57 LauncherThread.post(new Runnable() { 62 mHandler.post(new Runnable() {
58 @Override 63 @Override
59 public void run() { 64 public void run() {
60 Log.i(TAG, "onTrimMemory: level=%d, size=%d", level, size()) ; 65 Log.i(TAG, "onTrimMemory: level=%d, size=%d", level, size()) ;
61 if (size() <= 0) { 66 if (size() <= 0) {
62 return; 67 return;
63 } 68 }
64 if (level <= TRIM_MEMORY_RUNNING_MODERATE) { 69 if (level <= TRIM_MEMORY_RUNNING_MODERATE) {
65 reduce(MODERATE_BINDING_LOW_REDUCE_RATIO); 70 reduce(MODERATE_BINDING_LOW_REDUCE_RATIO);
66 } else if (level <= TRIM_MEMORY_RUNNING_LOW) { 71 } else if (level <= TRIM_MEMORY_RUNNING_LOW) {
67 reduce(MODERATE_BINDING_HIGH_REDUCE_RATIO); 72 reduce(MODERATE_BINDING_HIGH_REDUCE_RATIO);
68 } else if (level == TRIM_MEMORY_UI_HIDDEN) { 73 } else if (level == TRIM_MEMORY_UI_HIDDEN) {
69 // This will be handled by |mDelayedClearer|. 74 // This will be handled by |mDelayedClearer|.
70 return; 75 return;
71 } else { 76 } else {
72 evictAll(); 77 evictAll();
73 } 78 }
74 } 79 }
75 }); 80 });
76 } 81 }
77 82
78 @Override 83 @Override
79 public void onLowMemory() { 84 public void onLowMemory() {
80 ThreadUtils.assertOnUiThread(); 85 ThreadUtils.assertOnUiThread();
81 LauncherThread.post(new Runnable() { 86 mHandler.post(new Runnable() {
82 @Override 87 @Override
83 public void run() { 88 public void run() {
84 Log.i(TAG, "onLowMemory: evict %d bindings", size()); 89 Log.i(TAG, "onLowMemory: evict %d bindings", size());
85 evictAll(); 90 evictAll();
86 } 91 }
87 }); 92 });
88 } 93 }
89 94
90 @Override 95 @Override
91 public void onConfigurationChanged(Configuration configuration) {} 96 public void onConfigurationChanged(Configuration configuration) {}
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
146 if (mDelayedClearer == null) return; 151 if (mDelayedClearer == null) return;
147 mDelayedClearer = null; 152 mDelayedClearer = null;
148 Log.i(TAG, "Release moderate connections: %d", size()); 153 Log.i(TAG, "Release moderate connections: %d", size());
149 if (!onTesting) { 154 if (!onTesting) {
150 RecordHistogram.recordCountHistogram( 155 RecordHistogram.recordCountHistogram(
151 "Android.ModerateBindingCount", size()); 156 "Android.ModerateBindingCount", size());
152 } 157 }
153 evictAll(); 158 evictAll();
154 } 159 }
155 }; 160 };
156 LauncherThread.postDelayed(mDelayedClearer, MODERATE_BINDING_POOL_CL EARER_DELAY_MILLIS); 161 mHandler.postDelayed(mDelayedClearer, MODERATE_BINDING_POOL_CLEARER_ DELAY_MILLIS);
157 } 162 }
158 163
159 void onBroughtToForeground() { 164 void onBroughtToForeground() {
160 if (mDelayedClearer != null) { 165 if (mDelayedClearer != null) {
161 LauncherThread.removeCallbacks(mDelayedClearer); 166 mHandler.removeCallbacks(mDelayedClearer);
162 mDelayedClearer = null; 167 mDelayedClearer = null;
163 } 168 }
164 } 169 }
165 } 170 }
166 171
167 private ModerateBindingPool mModerateBindingPool; 172 private ModerateBindingPool mModerateBindingPool;
168 173
169 /** 174 /**
170 * Wraps ManagedChildProcessConnection keeping track of additional informati on needed to manage 175 * Wraps ManagedChildProcessConnection keeping track of additional informati on needed to manage
171 * the bindings of the connection. The reference to ManagedChildProcessConne ction is cleared 176 * the bindings of the connection. The reference to ManagedChildProcessConne ction is cleared
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 if (keepAsModerate) { 228 if (keepAsModerate) {
224 addConnectionToModerateBindingPool(connection); 229 addConnectionToModerateBindingPool(connection);
225 } 230 }
226 } 231 }
227 } 232 }
228 }; 233 };
229 234
230 if (mIsLowMemoryDevice) { 235 if (mIsLowMemoryDevice) {
231 doUnbind.run(); 236 doUnbind.run();
232 } else { 237 } else {
233 LauncherThread.postDelayed(doUnbind, DETACH_AS_ACTIVE_HIGH_END_D ELAY_MILLIS); 238 mHandler.postDelayed(doUnbind, DETACH_AS_ACTIVE_HIGH_END_DELAY_M ILLIS);
234 } 239 }
235 } 240 }
236 241
237 /** 242 /**
238 * Adds connection to the moderate binding pool. No-op if the connection has a strong 243 * Adds connection to the moderate binding pool. No-op if the connection has a strong
239 * binding. 244 * binding.
240 * @param connection The ChildProcessConnection to add to the moderate b inding pool. 245 * @param connection The ChildProcessConnection to add to the moderate b inding pool.
241 */ 246 */
242 private void addConnectionToModerateBindingPool(ManagedChildProcessConne ction connection) { 247 private void addConnectionToModerateBindingPool(ManagedChildProcessConne ction connection) {
243 if (mModerateBindingPool != null && !connection.isStrongBindingBound ()) { 248 if (mModerateBindingPool != null && !connection.isStrongBindingBound ()) {
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
331 // The connection bound with additional binding in onSentToBackground(). 336 // The connection bound with additional binding in onSentToBackground().
332 private ManagedConnection mBoundForBackgroundPeriod; 337 private ManagedConnection mBoundForBackgroundPeriod;
333 338
334 // Whether this instance is used on testing. 339 // Whether this instance is used on testing.
335 private final boolean mOnTesting; 340 private final boolean mOnTesting;
336 341
337 /** 342 /**
338 * The constructor is private to hide parameters exposed for testing from th e regular consumer. 343 * The constructor is private to hide parameters exposed for testing from th e regular consumer.
339 * Use factory methods to create an instance. 344 * Use factory methods to create an instance.
340 */ 345 */
341 private BindingManagerImpl(boolean isLowMemoryDevice, boolean onTesting) { 346 private BindingManagerImpl(Handler handler, boolean isLowMemoryDevice, boole an onTesting) {
342 assert LauncherThread.runningOnLauncherThread(); 347 mHandler = handler;
348 checkOnValidThread();
343 mIsLowMemoryDevice = isLowMemoryDevice; 349 mIsLowMemoryDevice = isLowMemoryDevice;
344 mOnTesting = onTesting; 350 mOnTesting = onTesting;
345 } 351 }
346 352
347 public static BindingManagerImpl createBindingManager() { 353 public static BindingManagerImpl createBindingManager(Handler handler) {
348 assert LauncherThread.runningOnLauncherThread(); 354 return new BindingManagerImpl(handler, SysUtils.isLowEndDevice(), false) ;
349 return new BindingManagerImpl(SysUtils.isLowEndDevice(), false);
350 } 355 }
351 356
352 /** 357 /**
353 * Creates a testing instance of BindingManager. Testing instance will have the unbinding delays 358 * Creates a testing instance of BindingManager. Testing instance will have the unbinding delays
354 * set to 0, so that the tests don't need to deal with actual waiting. 359 * set to 0, so that the tests don't need to deal with actual waiting.
355 * @param isLowEndDevice true iff the created instance should apply low-end binding policies 360 * @param isLowEndDevice true iff the created instance should apply low-end binding policies
356 */ 361 */
357 public static BindingManagerImpl createBindingManagerForTesting(boolean isLo wEndDevice) { 362 public static BindingManagerImpl createBindingManagerForTesting(
358 assert LauncherThread.runningOnLauncherThread(); 363 Handler handler, boolean isLowEndDevice) {
359 return new BindingManagerImpl(isLowEndDevice, true); 364 return new BindingManagerImpl(handler, isLowEndDevice, true);
360 } 365 }
361 366
362 @Override 367 @Override
363 public void addNewConnection(int pid, ManagedChildProcessConnection connecti on) { 368 public void addNewConnection(int pid, ManagedChildProcessConnection connecti on) {
364 assert LauncherThread.runningOnLauncherThread(); 369 checkOnValidThread();
365 // This will reset the previous entry for the pid in the unlikely event of the OS 370 // This will reset the previous entry for the pid in the unlikely event of the OS
366 // reusing renderer pids. 371 // reusing renderer pids.
367 mManagedConnections.put(pid, new ManagedConnection(connection)); 372 mManagedConnections.put(pid, new ManagedConnection(connection));
368 } 373 }
369 374
370 @Override 375 @Override
371 public void setInForeground(int pid, boolean inForeground) { 376 public void setInForeground(int pid, boolean inForeground) {
372 assert LauncherThread.runningOnLauncherThread(); 377 checkOnValidThread();
373 ManagedConnection managedConnection = mManagedConnections.get(pid); 378 ManagedConnection managedConnection = mManagedConnections.get(pid);
374 if (managedConnection == null) { 379 if (managedConnection == null) {
375 Log.w(TAG, "Cannot setInForeground() - never saw a connection for th e pid: %d", pid); 380 Log.w(TAG, "Cannot setInForeground() - never saw a connection for th e pid: %d", pid);
376 return; 381 return;
377 } 382 }
378 383
379 if (inForeground && mIsLowMemoryDevice && mLastInForeground != null 384 if (inForeground && mIsLowMemoryDevice && mLastInForeground != null
380 && mLastInForeground != managedConnection) { 385 && mLastInForeground != managedConnection) {
381 mLastInForeground.dropBindings(); 386 mLastInForeground.dropBindings();
382 } 387 }
383 388
384 managedConnection.setInForeground(inForeground); 389 managedConnection.setInForeground(inForeground);
385 if (inForeground) mLastInForeground = managedConnection; 390 if (inForeground) mLastInForeground = managedConnection;
386 } 391 }
387 392
388 @Override 393 @Override
389 public void onDeterminedVisibility(int pid) { 394 public void onDeterminedVisibility(int pid) {
390 assert LauncherThread.runningOnLauncherThread(); 395 checkOnValidThread();
391 ManagedConnection managedConnection = mManagedConnections.get(pid); 396 ManagedConnection managedConnection = mManagedConnections.get(pid);
392 if (managedConnection == null) { 397 if (managedConnection == null) {
393 Log.w(TAG, "Cannot call determinedVisibility() - never saw a connect ion for the pid: " 398 Log.w(TAG,
394 + "%d", pid); 399 "Cannot call determinedVisibility() - never saw a connection for the pid: "
400 + "%d",
401 pid);
395 return; 402 return;
396 } 403 }
397 404
398 managedConnection.onDeterminedVisibility(); 405 managedConnection.onDeterminedVisibility();
399 } 406 }
400 407
401 @Override 408 @Override
402 public void onSentToBackground() { 409 public void onSentToBackground() {
403 assert LauncherThread.runningOnLauncherThread(); 410 checkOnValidThread();
404 assert mBoundForBackgroundPeriod == null; 411 assert mBoundForBackgroundPeriod == null;
405 // mLastInForeground can be null at this point as the embedding applicat ion could be 412 // mLastInForeground can be null at this point as the embedding applicat ion could be
406 // used in foreground without spawning any renderers. 413 // used in foreground without spawning any renderers.
407 if (mLastInForeground != null) { 414 if (mLastInForeground != null) {
408 mLastInForeground.setBoundForBackgroundPeriod(true); 415 mLastInForeground.setBoundForBackgroundPeriod(true);
409 mBoundForBackgroundPeriod = mLastInForeground; 416 mBoundForBackgroundPeriod = mLastInForeground;
410 } 417 }
411 if (mModerateBindingPool != null) mModerateBindingPool.onSentToBackgroun d(mOnTesting); 418 if (mModerateBindingPool != null) mModerateBindingPool.onSentToBackgroun d(mOnTesting);
412 } 419 }
413 420
414 @Override 421 @Override
415 public void onBroughtToForeground() { 422 public void onBroughtToForeground() {
416 assert LauncherThread.runningOnLauncherThread(); 423 checkOnValidThread();
417 if (mBoundForBackgroundPeriod != null) { 424 if (mBoundForBackgroundPeriod != null) {
418 mBoundForBackgroundPeriod.setBoundForBackgroundPeriod(false); 425 mBoundForBackgroundPeriod.setBoundForBackgroundPeriod(false);
419 mBoundForBackgroundPeriod = null; 426 mBoundForBackgroundPeriod = null;
420 } 427 }
421 if (mModerateBindingPool != null) mModerateBindingPool.onBroughtToForegr ound(); 428 if (mModerateBindingPool != null) mModerateBindingPool.onBroughtToForegr ound();
422 } 429 }
423 430
424 @Override 431 @Override
425 public void removeConnection(int pid) { 432 public void removeConnection(int pid) {
426 assert LauncherThread.runningOnLauncherThread(); 433 checkOnValidThread();
427 ManagedConnection managedConnection = mManagedConnections.get(pid); 434 ManagedConnection managedConnection = mManagedConnections.get(pid);
428 if (managedConnection != null) { 435 if (managedConnection != null) {
429 mManagedConnections.remove(pid); 436 mManagedConnections.remove(pid);
430 managedConnection.clearConnection(); 437 managedConnection.clearConnection();
431 } 438 }
432 } 439 }
433 440
434 /** @return true iff the connection reference is no longer held */ 441 /** @return true iff the connection reference is no longer held */
435 @VisibleForTesting 442 @VisibleForTesting
436 public boolean isConnectionCleared(int pid) { 443 public boolean isConnectionCleared(int pid) {
437 assert LauncherThread.runningOnLauncherThread(); 444 checkOnValidThread();
438 return mManagedConnections.get(pid) == null; 445 return mManagedConnections.get(pid) == null;
439 } 446 }
440 447
441 @Override 448 @Override
442 public void startModerateBindingManagement(Context context, int maxSize) { 449 public void startModerateBindingManagement(Context context, int maxSize) {
443 assert LauncherThread.runningOnLauncherThread(); 450 checkOnValidThread();
444 if (mIsLowMemoryDevice) return; 451 if (mIsLowMemoryDevice) return;
445 452
446 if (mModerateBindingPool == null) { 453 if (mModerateBindingPool == null) {
447 Log.i(TAG, "Moderate binding enabled: maxSize=%d", maxSize); 454 Log.i(TAG, "Moderate binding enabled: maxSize=%d", maxSize);
448 mModerateBindingPool = new ModerateBindingPool(maxSize); 455 mModerateBindingPool = new ModerateBindingPool(maxSize);
449 if (context != null) { 456 if (context != null) {
450 // Note that it is safe to call Context.registerComponentCallbac ks from a background 457 // Note that it is safe to call Context.registerComponentCallbac ks from a background
451 // thread. 458 // thread.
452 context.registerComponentCallbacks(mModerateBindingPool); 459 context.registerComponentCallbacks(mModerateBindingPool);
453 } 460 }
454 } 461 }
455 } 462 }
456 463
457 @Override 464 @Override
458 public void releaseAllModerateBindings() { 465 public void releaseAllModerateBindings() {
459 assert LauncherThread.runningOnLauncherThread(); 466 checkOnValidThread();
460 if (mModerateBindingPool != null) { 467 if (mModerateBindingPool != null) {
461 Log.i(TAG, "Release all moderate bindings: %d", mModerateBindingPool .size()); 468 Log.i(TAG, "Release all moderate bindings: %d", mModerateBindingPool .size());
462 mModerateBindingPool.evictAll(); 469 mModerateBindingPool.evictAll();
463 } 470 }
464 } 471 }
472
473 /** Checks whether the caller is running on the thread specified at creation time. */
474 private final void checkOnValidThread() {
475 assert mHandler.getLooper() == Looper.myLooper();
476 }
465 } 477 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698