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.customtabs.test; | 5 package org.chromium.customtabs.test; |
6 | 6 |
7 import android.app.Activity; | 7 import android.app.Activity; |
8 import android.content.ComponentName; | 8 import android.content.ComponentName; |
9 import android.content.Intent; | 9 import android.content.Intent; |
10 import android.net.Uri; | 10 import android.net.Uri; |
11 import android.os.Bundle; | 11 import android.os.Bundle; |
12 import android.os.Handler; | 12 import android.os.Handler; |
| 13 import android.os.IBinder; |
13 import android.os.Looper; | 14 import android.os.Looper; |
14 import android.os.SystemClock; | 15 import android.os.SystemClock; |
15 import android.support.customtabs.CustomTabsCallback; | 16 import android.support.customtabs.CustomTabsCallback; |
16 import android.support.customtabs.CustomTabsClient; | 17 import android.support.customtabs.CustomTabsClient; |
17 import android.support.customtabs.CustomTabsIntent; | 18 import android.support.customtabs.CustomTabsIntent; |
18 import android.support.customtabs.CustomTabsServiceConnection; | 19 import android.support.customtabs.CustomTabsServiceConnection; |
19 import android.support.customtabs.CustomTabsSession; | 20 import android.support.customtabs.CustomTabsSession; |
| 21 import android.support.v4.app.BundleCompat; |
20 import android.util.Log; | 22 import android.util.Log; |
21 import android.view.View; | 23 import android.view.View; |
22 import android.widget.Button; | 24 import android.widget.Button; |
23 import android.widget.CheckBox; | 25 import android.widget.CheckBox; |
24 import android.widget.EditText; | 26 import android.widget.EditText; |
25 import android.widget.RadioButton; | 27 import android.widget.RadioButton; |
26 | 28 |
27 /** Activity used to benchmark Custom Tabs PLT. | 29 /** Activity used to benchmark Custom Tabs PLT. |
28 * | 30 * |
29 * This activity contains benchmark code for two modes: | 31 * This activity contains benchmark code for two modes: |
30 * 1. Comparison between a basic use of Custom Tabs and a basic use of WebView. | 32 * 1. Comparison between a basic use of Custom Tabs and a basic use of WebView. |
31 * 2. Custom Tabs benchmarking under various scenarios. | 33 * 2. Custom Tabs benchmarking under various scenarios. |
32 * | 34 * |
33 * The two modes are not merged into one as the metrics we can extract in the tw
o cases | 35 * The two modes are not merged into one as the metrics we can extract in the tw
o cases |
34 * are constrained for the first one by what WebView provides. | 36 * are constrained for the first one by what WebView provides. |
35 */ | 37 */ |
36 public class MainActivity extends Activity implements View.OnClickListener { | 38 public class MainActivity extends Activity implements View.OnClickListener { |
37 static final String TAG = "CUSTOMTABSBENCH"; | 39 static final String TAG = "CUSTOMTABSBENCH"; |
38 private static final String DEFAULT_URL = "https://www.android.com"; | 40 private static final String DEFAULT_URL = "https://www.android.com"; |
39 private static final String DEFAULT_PACKAGE = "com.google.android.apps.chrom
e"; | 41 private static final String DEFAULT_PACKAGE = "com.google.android.apps.chrom
e"; |
40 private static final int NONE = -1; | 42 private static final int NONE = -1; |
41 // Common key between the benchmark modes. | 43 // Common key between the benchmark modes. |
42 private static final String URL_KEY = "url"; | 44 private static final String URL_KEY = "url"; |
43 | 45 |
44 // Keys for the WebView / Custom Tabs comparison. | 46 // Keys for the WebView / Custom Tabs comparison. |
45 static final String INTENT_SENT_EXTRA = "intent_sent_ms"; | 47 static final String INTENT_SENT_EXTRA = "intent_sent_ms"; |
46 private static final String USE_WEBVIEW_KEY = "use_webview"; | 48 private static final String USE_WEBVIEW_KEY = "use_webview"; |
47 private static final String WARMUP_KEY = "warmup"; | 49 private static final String WARMUP_KEY = "warmup"; |
48 | 50 |
49 // Keep in sync with the same constants in CustomTabsConnection. | 51 // extraCommand related constants. |
50 private static final String DEBUG_OVERRIDE_KEY = | 52 private static final String SET_PRERENDER_ON_CELLULAR = "setPrerenderOnCellu
larForSession"; |
51 "android.support.customtabs.maylaunchurl.DEBUG_OVERRIDE"; | 53 private static final String SET_SPECULATION_MODE = "setSpeculationModeForSes
sion"; |
52 private static final int NO_OVERRIDE = 0; | 54 private static final String SET_IGNORE_URL_FRAGMENTS_FOR_SESSION = |
53 private static final int NO_PRERENDERING = 1; | 55 "setIgnoreUrlFragmentsForSession"; |
54 private static final int PREFETCH_ONLY = 2; | 56 private static final int NO_SPECULATION = 0; |
55 // Only for reporting. | 57 private static final int PRERENDER = 2; |
56 private static final int NO_STATE_PREFETCH = 3; | 58 private static final int HIDDEN_TAB = 3; |
57 | 59 |
58 private final Handler mHandler = new Handler(Looper.getMainLooper()); | 60 private final Handler mHandler = new Handler(Looper.getMainLooper()); |
59 | 61 |
60 private EditText mUrlEditText; | 62 private EditText mUrlEditText; |
61 private RadioButton mChromeRadioButton; | 63 private RadioButton mChromeRadioButton; |
62 private RadioButton mWebViewRadioButton; | 64 private RadioButton mWebViewRadioButton; |
63 private CheckBox mWarmupCheckbox; | 65 private CheckBox mWarmupCheckbox; |
64 private long mIntentSentMs; | 66 private long mIntentSentMs; |
65 | 67 |
66 @Override | 68 @Override |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 return System.currentTimeMillis(); | 212 return System.currentTimeMillis(); |
211 } | 213 } |
212 | 214 |
213 /** Start the second benchmark mode. | 215 /** Start the second benchmark mode. |
214 * | 216 * |
215 * NOTE: Methods below are for the second mode. | 217 * NOTE: Methods below are for the second mode. |
216 */ | 218 */ |
217 private void startCustomTabsBenchmark(Intent intent) { | 219 private void startCustomTabsBenchmark(Intent intent) { |
218 String url = intent.getStringExtra(URL_KEY); | 220 String url = intent.getStringExtra(URL_KEY); |
219 if (url == null) url = DEFAULT_URL; | 221 if (url == null) url = DEFAULT_URL; |
| 222 String speculatedUrl = intent.getStringExtra("speculated_url"); |
| 223 if (speculatedUrl == null) speculatedUrl = url; |
220 String packageName = intent.getStringExtra("package_name"); | 224 String packageName = intent.getStringExtra("package_name"); |
221 if (packageName == null) packageName = DEFAULT_PACKAGE; | 225 if (packageName == null) packageName = DEFAULT_PACKAGE; |
222 boolean warmup = intent.getBooleanExtra("warmup", false); | 226 boolean warmup = intent.getBooleanExtra("warmup", false); |
223 int delayToMayLaunchUrl = intent.getIntExtra("delay_to_may_launch_url",
NONE); | 227 int delayToMayLaunchUrl = intent.getIntExtra("delay_to_may_launch_url",
NONE); |
224 int delayToLaunchUrl = intent.getIntExtra("delay_to_launch_url", NONE); | 228 int delayToLaunchUrl = intent.getIntExtra("delay_to_launch_url", NONE); |
225 | 229 String speculationMode = intent.getStringExtra("speculation_mode"); |
226 int speculationMode = 0; | 230 if (speculationMode == null) speculationMode = "prerender"; |
227 String speculationModeValue = intent.getStringExtra("speculation_mode"); | |
228 switch (speculationModeValue) { | |
229 case "prerender": | |
230 speculationMode = NO_OVERRIDE; | |
231 break; | |
232 case "disabled": | |
233 speculationMode = NO_PRERENDERING; | |
234 break; | |
235 case "speculative_prefetch": | |
236 speculationMode = PREFETCH_ONLY; | |
237 break; | |
238 case "no_state_prefetch": | |
239 speculationMode = NO_STATE_PREFETCH; | |
240 break; | |
241 default: | |
242 throw new IllegalArgumentException( | |
243 "Invalid prerender mode: " + speculationModeValue); | |
244 } | |
245 | |
246 int timeoutSeconds = intent.getIntExtra("timeout", NONE); | 231 int timeoutSeconds = intent.getIntExtra("timeout", NONE); |
247 | 232 |
248 launchCustomTabs(packageName, url, warmup, speculationMode, delayToMayLa
unchUrl, | 233 launchCustomTabs(packageName, speculatedUrl, url, warmup, speculationMod
e, |
249 delayToLaunchUrl, timeoutSeconds); | 234 delayToMayLaunchUrl, delayToLaunchUrl, timeoutSeconds); |
250 } | 235 } |
251 | 236 |
252 private final class CustomCallback extends CustomTabsCallback { | 237 private final class CustomCallback extends CustomTabsCallback { |
253 private final boolean mWarmup; | 238 private final boolean mWarmup; |
254 private final int mSpeculationMode; | 239 private final String mSpeculationMode; |
255 private final int mDelayToMayLaunchUrl; | 240 private final int mDelayToMayLaunchUrl; |
256 private final int mDelayToLaunchUrl; | 241 private final int mDelayToLaunchUrl; |
257 private long mIntentSentMs = NONE; | 242 private long mIntentSentMs = NONE; |
258 private long mPageLoadStartedMs = NONE; | 243 private long mPageLoadStartedMs = NONE; |
259 private long mPageLoadFinishedMs = NONE; | 244 private long mPageLoadFinishedMs = NONE; |
260 private long mFirstContentfulPaintMs = NONE; | 245 private long mFirstContentfulPaintMs = NONE; |
261 | 246 |
262 public CustomCallback(boolean warmup, int speculationMode, int delayToMa
yLaunchUrl, | 247 public CustomCallback(boolean warmup, String speculationMode, int delayT
oMayLaunchUrl, |
263 int delayToLaunchUrl) { | 248 int delayToLaunchUrl) { |
264 mWarmup = warmup; | 249 mWarmup = warmup; |
265 mSpeculationMode = speculationMode; | 250 mSpeculationMode = speculationMode; |
266 mDelayToMayLaunchUrl = delayToMayLaunchUrl; | 251 mDelayToMayLaunchUrl = delayToMayLaunchUrl; |
267 mDelayToLaunchUrl = delayToLaunchUrl; | 252 mDelayToLaunchUrl = delayToLaunchUrl; |
268 } | 253 } |
269 | 254 |
270 public void recordIntentHasBeenSent() { | 255 public void recordIntentHasBeenSent() { |
271 mIntentSentMs = SystemClock.uptimeMillis(); | 256 mIntentSentMs = SystemClock.uptimeMillis(); |
272 } | 257 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 public void logMetricsAndFinishDelayed(int delayMs) { | 303 public void logMetricsAndFinishDelayed(int delayMs) { |
319 mHandler.postDelayed(new Runnable() { | 304 mHandler.postDelayed(new Runnable() { |
320 @Override | 305 @Override |
321 public void run() { | 306 public void run() { |
322 logMetricsAndFinish(); | 307 logMetricsAndFinish(); |
323 } | 308 } |
324 }, delayMs); | 309 }, delayMs); |
325 } | 310 } |
326 } | 311 } |
327 | 312 |
328 private void onCustomTabsServiceConnected(CustomTabsClient client, final Uri
uri, | 313 private static void forceSpeculationMode( |
329 final CustomCallback cb, boolean warmup, final int prerenderMode, | 314 CustomTabsClient client, IBinder sessionBinder, String speculationMo
de) { |
| 315 // The same bundle can be used for all calls, as the commands only look
for their own |
| 316 // arguments in it. |
| 317 Bundle params = new Bundle(); |
| 318 BundleCompat.putBinder(params, "session", sessionBinder); |
| 319 params.putBoolean("ignoreFragments", true); |
| 320 params.putBoolean("prerender", true); |
| 321 |
| 322 int speculationModeValue = 0; |
| 323 switch (speculationMode) { |
| 324 case "disabled": |
| 325 speculationModeValue = NO_SPECULATION; |
| 326 break; |
| 327 case "prerender": |
| 328 speculationModeValue = PRERENDER; |
| 329 break; |
| 330 case "hidden_tab": |
| 331 speculationModeValue = HIDDEN_TAB; |
| 332 break; |
| 333 default: |
| 334 throw new RuntimeException("Invalid speculation mode"); |
| 335 } |
| 336 params.putInt("speculationMode", speculationModeValue); |
| 337 |
| 338 boolean ok = client.extraCommand(SET_PRERENDER_ON_CELLULAR, params) != n
ull; |
| 339 if (!ok) throw new RuntimeException("Cannot set cellular prerendering"); |
| 340 ok = client.extraCommand(SET_IGNORE_URL_FRAGMENTS_FOR_SESSION, params) !
= null; |
| 341 if (!ok) throw new RuntimeException("Cannot set ignoreFragments"); |
| 342 ok = client.extraCommand(SET_SPECULATION_MODE, params) != null; |
| 343 if (!ok) throw new RuntimeException("Cannot set the speculation mode"); |
| 344 } |
| 345 |
| 346 private void onCustomTabsServiceConnected(CustomTabsClient client, final Uri
speculatedUri, |
| 347 final Uri uri, final CustomCallback cb, boolean warmup, String specu
lationMode, |
330 int delayToMayLaunchUrl, final int delayToLaunchUrl, final int timeo
utSeconds) { | 348 int delayToMayLaunchUrl, final int delayToLaunchUrl, final int timeo
utSeconds) { |
331 final CustomTabsSession session = client.newSession(cb); | 349 final CustomTabsSession session = client.newSession(cb); |
332 final CustomTabsIntent intent = (new CustomTabsIntent.Builder(session)).
build(); | 350 final CustomTabsIntent intent = (new CustomTabsIntent.Builder(session)).
build(); |
| 351 |
| 352 IBinder sessionBinder = |
| 353 BundleCompat.getBinder(intent.intent.getExtras(), CustomTabsInte
nt.EXTRA_SESSION); |
| 354 assert sessionBinder != null; |
| 355 forceSpeculationMode(client, sessionBinder, speculationMode); |
| 356 |
333 final Runnable launchRunnable = new Runnable() { | 357 final Runnable launchRunnable = new Runnable() { |
334 @Override | 358 @Override |
335 public void run() { | 359 public void run() { |
336 intent.launchUrl(MainActivity.this, uri); | 360 intent.launchUrl(MainActivity.this, uri); |
337 cb.recordIntentHasBeenSent(); | 361 cb.recordIntentHasBeenSent(); |
338 if (timeoutSeconds != NONE) cb.logMetricsAndFinishDelayed(timeou
tSeconds * 1000); | 362 if (timeoutSeconds != NONE) cb.logMetricsAndFinishDelayed(timeou
tSeconds * 1000); |
339 } | 363 } |
340 }; | 364 }; |
341 Runnable mayLaunchRunnable = new Runnable() { | 365 Runnable mayLaunchRunnable = new Runnable() { |
342 @Override | 366 @Override |
343 public void run() { | 367 public void run() { |
344 Bundle extras = new Bundle(); | 368 session.mayLaunchUrl(speculatedUri, null, null); |
345 if (prerenderMode == NO_PRERENDERING) { | |
346 extras.putInt(DEBUG_OVERRIDE_KEY, NO_PRERENDERING); | |
347 } else if (prerenderMode != NO_STATE_PREFETCH) { | |
348 extras.putInt(DEBUG_OVERRIDE_KEY, prerenderMode); | |
349 } | |
350 | |
351 session.mayLaunchUrl(uri, extras, null); | |
352 mHandler.postDelayed(launchRunnable, delayToLaunchUrl); | 369 mHandler.postDelayed(launchRunnable, delayToLaunchUrl); |
353 } | 370 } |
354 }; | 371 }; |
355 | 372 |
356 if (warmup) client.warmup(0); | 373 if (warmup) client.warmup(0); |
357 if (delayToMayLaunchUrl != NONE) { | 374 if (delayToMayLaunchUrl != NONE) { |
358 mHandler.postDelayed(mayLaunchRunnable, delayToMayLaunchUrl); | 375 mHandler.postDelayed(mayLaunchRunnable, delayToMayLaunchUrl); |
359 } else { | 376 } else { |
360 mHandler.postDelayed(launchRunnable, delayToLaunchUrl); | 377 mHandler.postDelayed(launchRunnable, delayToLaunchUrl); |
361 } | 378 } |
362 } | 379 } |
363 | 380 |
364 private void launchCustomTabs(String packageName, String url, final boolean
warmup, | 381 private void launchCustomTabs(String packageName, String speculatedUrl, Stri
ng url, |
365 final int speculationMode, final int delayToMayLaunchUrl, final int
delayToLaunchUrl, | 382 final boolean warmup, final String speculationMode, final int delayT
oMayLaunchUrl, |
366 final int timeoutSeconds) { | 383 final int delayToLaunchUrl, final int timeoutSeconds) { |
367 final CustomCallback cb = | 384 final CustomCallback cb = |
368 new CustomCallback(warmup, speculationMode, delayToMayLaunchUrl,
delayToLaunchUrl); | 385 new CustomCallback(warmup, speculationMode, delayToMayLaunchUrl,
delayToLaunchUrl); |
| 386 final Uri speculatedUri = Uri.parse(speculatedUrl); |
369 final Uri uri = Uri.parse(url); | 387 final Uri uri = Uri.parse(url); |
370 CustomTabsClient.bindCustomTabsService( | 388 CustomTabsClient.bindCustomTabsService( |
371 this, packageName, new CustomTabsServiceConnection() { | 389 this, packageName, new CustomTabsServiceConnection() { |
372 @Override | 390 @Override |
373 public void onCustomTabsServiceConnected( | 391 public void onCustomTabsServiceConnected( |
374 ComponentName name, final CustomTabsClient client) { | 392 ComponentName name, final CustomTabsClient client) { |
375 MainActivity.this.onCustomTabsServiceConnected(client, u
ri, cb, warmup, | 393 MainActivity.this.onCustomTabsServiceConnected(client, s
peculatedUri, uri, |
376 speculationMode, delayToMayLaunchUrl, delayToLau
nchUrl, | 394 cb, warmup, speculationMode, delayToMayLaunchUrl
, delayToLaunchUrl, |
377 timeoutSeconds); | 395 timeoutSeconds); |
378 } | 396 } |
379 | 397 |
380 @Override | 398 @Override |
381 public void onServiceDisconnected(ComponentName name) {} | 399 public void onServiceDisconnected(ComponentName name) {} |
382 }); | 400 }); |
383 } | 401 } |
384 } | 402 } |
OLD | NEW |