1# Copyright 2013 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
5import os
6
7from telemetry.internal.util import binary_manager
8from telemetry.internal.backends.chrome import android_browser_finder
9from telemetry.internal.platform import profiler
10
11from devil.android.sdk import intent  # pylint: disable=import-error
12
13class UnableToFindApplicationException(Exception):
14  """Exception when unable to find a launched application"""
15
16  def __init__(self, application):
17    super(UnableToFindApplicationException, self).__init__()
18    self.application = application
19
20  def __str__(self):
21    return repr(self.application)
22
23
24class OOMKillerProfiler(profiler.Profiler):
25  """Android-specific, Launch the music application and check it is still alive
26  at the end of the run."""
27
28  def __init__(self, browser_backend, platform_backend, output_path, state):
29    super(OOMKillerProfiler, self).__init__(
30        browser_backend, platform_backend, output_path, state)
31    if not 'mem_consumer_launched' in state:
32      state['mem_consumer_launched'] = True
33      arch_name = self._browser_backend.device.GetABI()
34      mem_consumer_path = binary_manager.FetchPath(
35          os.path.join('apks', 'MemConsumer.apk'), arch_name, 'android')
36      assert mem_consumer_path, ('Could not find memconsumer app. Please build '
37                                 'memconsumer target.')
38      if not self._platform_backend.CanLaunchApplication(
39          'org.chromium.memconsumerg'):
40        self._platform_backend.InstallApplication(mem_consumer_path)
41      self._browser_backend.device.GoHome()
42      self._platform_backend.LaunchApplication(
43          'org.chromium.memconsumer/.MemConsumer',
44          '--ei memory 20')
45      # Bring the browser to the foreground after launching the mem consumer
46      self._browser_backend.device.StartActivity(
47          intent.Intent(package=browser_backend.package,
48                        activity=browser_backend.activity),
49          blocking=True)
50
51  @classmethod
52  def name(cls):
53    return 'oomkiller'
54
55  @classmethod
56  def is_supported(cls, browser_type):
57    if browser_type == 'any':
58      return android_browser_finder.CanFindAvailableBrowsers()
59    return browser_type.startswith('android')
60
61  @classmethod
62  def WillCloseBrowser(cls, browser_backend, platform_backend):
63    browser_backend.device.ForceStop('org.chromium.memconsumer')
64
65  def CollectProfile(self):
66    missing_applications = self._MissingApplications()
67    if not len(missing_applications):
68      return []
69    raise UnableToFindApplicationException(', '.join(missing_applications))
70
71  def _MissingApplications(self):
72    # TODO(qsr): Add com.android.launcher to the list, when the reason why the
73    # launcher is often killed is understood.
74    must_have_apps = [
75        'org.chromium.memconsumer',
76    ]
77    return [app for app in must_have_apps if
78            not self._platform_backend.IsApplicationRunning(app)]
79