OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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.chrome.browser.customtabs; | 5 package org.chromium.chrome.browser.customtabs; |
6 | 6 |
7 import android.app.ActivityManager; | 7 import android.app.ActivityManager; |
8 import android.app.Application; | 8 import android.app.Application; |
9 import android.content.ComponentName; | 9 import android.content.ComponentName; |
10 import android.content.Context; | 10 import android.content.Context; |
11 import android.content.Intent; | 11 import android.content.Intent; |
12 import android.content.ServiceConnection; | 12 import android.content.ServiceConnection; |
13 import android.content.pm.PackageManager; | 13 import android.content.pm.PackageManager; |
14 import android.content.res.Resources; | 14 import android.content.res.Resources; |
15 import android.graphics.Point; | 15 import android.graphics.Point; |
16 import android.net.ConnectivityManager; | 16 import android.net.ConnectivityManager; |
17 import android.net.Uri; | 17 import android.net.Uri; |
18 import android.os.AsyncTask; | 18 import android.os.AsyncTask; |
19 import android.os.Binder; | 19 import android.os.Binder; |
20 import android.os.Build; | 20 import android.os.Build; |
21 import android.os.Bundle; | 21 import android.os.Bundle; |
22 import android.os.IBinder; | 22 import android.os.IBinder; |
23 import android.os.Process; | 23 import android.os.Process; |
24 import android.os.RemoteException; | 24 import android.os.RemoteException; |
25 import android.os.SystemClock; | 25 import android.os.SystemClock; |
26 import android.support.customtabs.ICustomTabsCallback; | 26 import android.support.customtabs.ICustomTabsCallback; |
27 import android.support.customtabs.ICustomTabsService; | 27 import android.support.customtabs.ICustomTabsService; |
28 import android.text.TextUtils; | 28 import android.text.TextUtils; |
29 import android.util.SparseArray; | 29 import android.util.SparseArray; |
30 import android.util.SparseBooleanArray; | |
30 import android.view.WindowManager; | 31 import android.view.WindowManager; |
31 | 32 |
32 import org.chromium.base.FieldTrialList; | 33 import org.chromium.base.FieldTrialList; |
33 import org.chromium.base.Log; | 34 import org.chromium.base.Log; |
34 import org.chromium.base.ThreadUtils; | 35 import org.chromium.base.ThreadUtils; |
35 import org.chromium.base.VisibleForTesting; | 36 import org.chromium.base.VisibleForTesting; |
36 import org.chromium.base.annotations.SuppressFBWarnings; | 37 import org.chromium.base.annotations.SuppressFBWarnings; |
37 import org.chromium.base.library_loader.ProcessInitException; | 38 import org.chromium.base.library_loader.ProcessInitException; |
38 import org.chromium.base.metrics.RecordHistogram; | 39 import org.chromium.base.metrics.RecordHistogram; |
39 import org.chromium.chrome.R; | 40 import org.chromium.chrome.R; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
72 private static final String TAG = "cr.ChromeConnection"; | 73 private static final String TAG = "cr.ChromeConnection"; |
73 @VisibleForTesting | 74 @VisibleForTesting |
74 static final String NO_PRERENDERING_KEY = | 75 static final String NO_PRERENDERING_KEY = |
75 "android.support.customtabs.maylaunchurl.NO_PRERENDERING"; | 76 "android.support.customtabs.maylaunchurl.NO_PRERENDERING"; |
76 | 77 |
77 // Values for the "CustomTabs.PredictionStatus" UMA histogram. Append-only. | 78 // Values for the "CustomTabs.PredictionStatus" UMA histogram. Append-only. |
78 private static final int NO_PREDICTION = 0; | 79 private static final int NO_PREDICTION = 0; |
79 private static final int GOOD_PREDICTION = 1; | 80 private static final int GOOD_PREDICTION = 1; |
80 private static final int BAD_PREDICTION = 2; | 81 private static final int BAD_PREDICTION = 2; |
81 private static final int PREDICTION_STATUS_COUNT = 3; | 82 private static final int PREDICTION_STATUS_COUNT = 3; |
83 // Values for the "CustomTabs.CalledWarmup" UMA histogram. Append-only. | |
pasko
2015/09/03 18:02:19
nittynit: empty line above would look nicer
Benoit L
2015/09/29 09:04:23
Ack.
| |
84 private static final int NO_SESSION_NO_WARMUP = 0; | |
85 private static final int NO_SESSION_WARMUP = 1; | |
86 private static final int SESSION_NO_WARMUP_ALREADY_CALLED = 2; | |
87 private static final int SESSION_NO_WARMUP_NOT_CALLED = 3; | |
88 private static final int SESSION_WARMUP = 4; | |
89 private static final int SESSION_WARMUP_COUNT = 5; | |
82 | 90 |
83 private static AtomicReference<CustomTabsConnection> sInstance = | 91 private static AtomicReference<CustomTabsConnection> sInstance = |
84 new AtomicReference<CustomTabsConnection>(); | 92 new AtomicReference<CustomTabsConnection>(); |
85 | 93 |
86 private static final class PrerenderedUrlParams { | 94 private static final class PrerenderedUrlParams { |
87 public final IBinder mSession; | 95 public final IBinder mSession; |
88 public final WebContents mWebContents; | 96 public final WebContents mWebContents; |
89 public final String mUrl; | 97 public final String mUrl; |
90 public final String mReferrer; | 98 public final String mReferrer; |
91 public final Bundle mExtras; | 99 public final Bundle mExtras; |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
184 | 192 |
185 public String getPredictedUrl() { | 193 public String getPredictedUrl() { |
186 return mPredictedUrl; | 194 return mPredictedUrl; |
187 } | 195 } |
188 | 196 |
189 public long getLastMayLaunchUrlTimestamp() { | 197 public long getLastMayLaunchUrlTimestamp() { |
190 return mLastMayLaunchUrlTimestamp; | 198 return mLastMayLaunchUrlTimestamp; |
191 } | 199 } |
192 } | 200 } |
193 | 201 |
194 private final Object mLock = new Object(); | 202 private final Object mLock = new Object(); |
pasko
2015/09/03 18:02:20
please add a comment saying something like: 'mLock
Benoit L
2015/09/29 09:04:23
Refactored this, so... done?
| |
195 private final Map<IBinder, SessionParams> mSessionParams = new HashMap<>(); | 203 private final Map<IBinder, SessionParams> mSessionParams = new HashMap<>(); |
196 // Prediction tracking is done by UID and not by session, since a | 204 // Prediction tracking is done by UID and not by session, since a |
197 // mis-behaving application can create a large number of sessions. | 205 // mis-behaving application can create a large number of sessions. |
198 private SparseArray<PredictionStats> mUidToPredictionsStats = new SparseArra y<>(); | 206 private SparseArray<PredictionStats> mUidToPredictionsStats = new SparseArra y<>(); |
207 // Whether a client application has called warmup() in this instance lifetim e. | |
208 private SparseBooleanArray mUidHasCalledWarmup = new SparseBooleanArray(); | |
199 | 209 |
200 /** | 210 /** |
201 * <strong>DO NOT CALL</strong> | 211 * <strong>DO NOT CALL</strong> |
202 * Public to be instanciable from {@link ChromeApplication}. This is however | 212 * Public to be instanciable from {@link ChromeApplication}. This is however |
203 * intended to be private. | 213 * intended to be private. |
204 */ | 214 */ |
205 public CustomTabsConnection(Application application) { | 215 public CustomTabsConnection(Application application) { |
206 super(); | 216 super(); |
207 mApplication = application; | 217 mApplication = application; |
208 } | 218 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
254 mUidToPredictionsStats.put(uid, new PredictionStats()); | 264 mUidToPredictionsStats.put(uid, new PredictionStats()); |
255 } | 265 } |
256 } | 266 } |
257 return true; | 267 return true; |
258 } | 268 } |
259 | 269 |
260 @Override | 270 @Override |
261 public boolean warmup(long flags) { | 271 public boolean warmup(long flags) { |
262 // Here and in mayLaunchUrl(), don't do expensive work for background ap plications. | 272 // Here and in mayLaunchUrl(), don't do expensive work for background ap plications. |
263 if (!isCallerForegroundOrSelf()) return false; | 273 if (!isCallerForegroundOrSelf()) return false; |
274 | |
275 synchronized (mLock) { | |
276 mUidHasCalledWarmup.put(Binder.getCallingUid(), true); | |
277 } | |
278 | |
264 if (!mWarmupHasBeenCalled.compareAndSet(false, true)) return true; | 279 if (!mWarmupHasBeenCalled.compareAndSet(false, true)) return true; |
265 // The call is non-blocking and this must execute on the UI thread, post a task. | 280 // The call is non-blocking and this must execute on the UI thread, post a task. |
266 ThreadUtils.postOnUiThread(new Runnable() { | 281 ThreadUtils.postOnUiThread(new Runnable() { |
267 @Override | 282 @Override |
268 @SuppressFBWarnings("DM_EXIT") | 283 @SuppressFBWarnings("DM_EXIT") |
269 public void run() { | 284 public void run() { |
270 ChromeApplication app = (ChromeApplication) mApplication; | 285 ChromeApplication app = (ChromeApplication) mApplication; |
271 try { | 286 try { |
272 app.startBrowserProcessesAndLoadLibrariesSync(true); | 287 app.startBrowserProcessesAndLoadLibrariesSync(true); |
273 } catch (ProcessInitException e) { | 288 } catch (ProcessInitException e) { |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
377 } | 392 } |
378 | 393 |
379 /** | 394 /** |
380 * Registers a launch of a |url| for a given |session|. | 395 * Registers a launch of a |url| for a given |session|. |
381 * | 396 * |
382 * This is used for accounting. | 397 * This is used for accounting. |
383 */ | 398 */ |
384 void registerLaunch(IBinder session, String url) { | 399 void registerLaunch(IBinder session, String url) { |
385 int outcome; | 400 int outcome; |
386 long elapsedTimeMs = -1; | 401 long elapsedTimeMs = -1; |
402 boolean hasValidSession = false; | |
403 boolean hasUidCalledWarmup = false; | |
387 synchronized (mLock) { | 404 synchronized (mLock) { |
388 SessionParams sessionParams = mSessionParams.get(session); | 405 SessionParams sessionParams = mSessionParams.get(session); |
389 if (sessionParams == null) { | 406 if (sessionParams == null) { |
390 outcome = NO_PREDICTION; | 407 outcome = NO_PREDICTION; |
391 } else { | 408 } else { |
409 hasValidSession = true; | |
410 hasUidCalledWarmup = mUidHasCalledWarmup.get(sessionParams.mUid) ; | |
411 | |
392 String predictedUrl = sessionParams.getPredictedUrl(); | 412 String predictedUrl = sessionParams.getPredictedUrl(); |
393 outcome = predictedUrl == null ? NO_PREDICTION | 413 outcome = predictedUrl == null ? NO_PREDICTION |
394 : predictedUrl.equals(url) ? GOOD_PREDICTION : BAD_PREDI CTION; | 414 : predictedUrl.equals(url) ? GOOD_PREDICTION : BAD_PREDI CTION; |
395 elapsedTimeMs = SystemClock.elapsedRealtime() | 415 elapsedTimeMs = SystemClock.elapsedRealtime() |
396 - sessionParams.getLastMayLaunchUrlTimestamp(); | 416 - sessionParams.getLastMayLaunchUrlTimestamp(); |
397 sessionParams.setPredictionMetrics(null, 0); | 417 sessionParams.setPredictionMetrics(null, 0); |
398 if (outcome == GOOD_PREDICTION) { | 418 if (outcome == GOOD_PREDICTION) { |
399 // If the prediction was correct, back to the smallest | 419 // If the prediction was correct, back to the smallest |
400 // throttling level. | 420 // throttling level. |
401 mUidToPredictionsStats.put(sessionParams.mUid, new Predictio nStats()); | 421 mUidToPredictionsStats.put(sessionParams.mUid, new Predictio nStats()); |
402 } | 422 } |
403 } | 423 } |
404 } | 424 } |
405 RecordHistogram.recordEnumeratedHistogram( | 425 RecordHistogram.recordEnumeratedHistogram( |
406 "CustomTabs.PredictionStatus", outcome, PREDICTION_STATUS_COUNT) ; | 426 "CustomTabs.PredictionStatus", outcome, PREDICTION_STATUS_COUNT) ; |
407 if (outcome == GOOD_PREDICTION) { | 427 if (outcome == GOOD_PREDICTION) { |
408 RecordHistogram.recordCustomTimesHistogram("CustomTabs.PredictionToL aunch", | 428 RecordHistogram.recordCustomTimesHistogram("CustomTabs.PredictionToL aunch", |
409 elapsedTimeMs, 1, TimeUnit.MINUTES.toMillis(3), TimeUnit.MIL LISECONDS, 100); | 429 elapsedTimeMs, 1, TimeUnit.MINUTES.toMillis(3), TimeUnit.MIL LISECONDS, 100); |
410 } | 430 } |
431 // CustomTabs.CalledWarmup histogram. | |
432 boolean warmupCalled = mWarmupHasBeenCalled.get(); | |
433 int warmupKind = warmupCalled ? NO_SESSION_WARMUP : NO_SESSION_NO_WARMUP ; | |
434 if (hasValidSession) { | |
435 if (hasUidCalledWarmup) { | |
436 warmupKind = SESSION_WARMUP; | |
437 } else { | |
438 warmupKind = warmupCalled ? SESSION_NO_WARMUP_ALREADY_CALLED | |
439 : SESSION_NO_WARMUP_NOT_CALLED; | |
440 } | |
441 } | |
442 RecordHistogram.recordEnumeratedHistogram( | |
443 "CustomTabs.CalledWarmup", warmupKind, SESSION_WARMUP_COUNT); | |
411 } | 444 } |
412 | 445 |
413 /** | 446 /** |
414 * Transfers a prerendered WebContents if one exists. | 447 * Transfers a prerendered WebContents if one exists. |
415 * | 448 * |
416 * This resets the internal WebContents; a subsequent call to this method | 449 * This resets the internal WebContents; a subsequent call to this method |
417 * returns null. Must be called from the UI thread. | 450 * returns null. Must be called from the UI thread. |
418 * If a prerender exists for a different URL with the same sessionId or with | 451 * If a prerender exists for a different URL with the same sessionId or with |
419 * a different referrer, then this is treated as a mispredict from the | 452 * a different referrer, then this is treated as a mispredict from the |
420 * client application, and cancels the previous prerender. This is done to | 453 * client application, and cancels the previous prerender. This is done to |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
630 } | 663 } |
631 | 664 |
632 /** | 665 /** |
633 * Called when a remote client has died. | 666 * Called when a remote client has died. |
634 */ | 667 */ |
635 private void cleanupAlreadyLocked(IBinder session) { | 668 private void cleanupAlreadyLocked(IBinder session) { |
636 ThreadUtils.assertOnUiThread(); | 669 ThreadUtils.assertOnUiThread(); |
637 SessionParams params = mSessionParams.get(session); | 670 SessionParams params = mSessionParams.get(session); |
638 if (params == null) return; | 671 if (params == null) return; |
639 mSessionParams.remove(session); | 672 mSessionParams.remove(session); |
673 mUidHasCalledWarmup.delete(params.mUid); | |
640 IBinder binder = params.mCallback.asBinder(); | 674 IBinder binder = params.mCallback.asBinder(); |
641 binder.unlinkToDeath(params.mDeathRecipient, 0); | 675 binder.unlinkToDeath(params.mDeathRecipient, 0); |
642 if (mPrerender != null && session.equals(mPrerender.mSession)) { | 676 if (mPrerender != null && session.equals(mPrerender.mSession)) { |
643 prerenderUrl(session, null, null); // Cancels the pre-render. | 677 prerenderUrl(session, null, null); // Cancels the pre-render. |
644 } | 678 } |
645 } | 679 } |
646 | 680 |
647 private boolean mayPrerender() { | 681 private boolean mayPrerender() { |
648 if (FieldTrialList.findFullName("CustomTabs").equals("DisablePrerender") ) return false; | 682 if (FieldTrialList.findFullName("CustomTabs").equals("DisablePrerender") ) return false; |
649 if (!DeviceClassManager.enablePrerendering()) return false; | 683 if (!DeviceClassManager.enablePrerendering()) return false; |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
717 return screenSize; | 751 return screenSize; |
718 } | 752 } |
719 | 753 |
720 @VisibleForTesting | 754 @VisibleForTesting |
721 void resetThrottling(int uid) { | 755 void resetThrottling(int uid) { |
722 synchronized (mLock) { | 756 synchronized (mLock) { |
723 mUidToPredictionsStats.put(uid, new PredictionStats()); | 757 mUidToPredictionsStats.put(uid, new PredictionStats()); |
724 } | 758 } |
725 } | 759 } |
726 } | 760 } |
OLD | NEW |