1eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch# Copyright 2013 The Chromium Authors. All rights reserved.
2eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch# Use of this source code is governed by a BSD-style license that can be
3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch# found in the LICENSE file.
4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch""" A simple device interface for build steps.
6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch"""
8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
9eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochimport logging
10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochimport os
11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochimport re
12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochimport sys
13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)from util import build_utils
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochBUILD_ANDROID_DIR = os.path.join(os.path.dirname(__file__), '..', '..')
17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochsys.path.append(BUILD_ANDROID_DIR)
18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochfrom pylib import android_commands
20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)from pylib.device import device_errors
21a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochfrom pylib.device import device_utils
22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)GetAttachedDevices = android_commands.GetAttachedDevices
24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass BuildDevice(object):
27eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  def __init__(self, configuration):
28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    self.id = configuration['id']
29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    self.description = configuration['description']
30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    self.install_metadata = configuration['install_metadata']
31a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    self.device = device_utils.DeviceUtils(self.id)
32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  def RunShellCommand(self, *args, **kwargs):
34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return self.device.RunShellCommand(*args, **kwargs)
35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
36116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  def PushChangedFiles(self, *args, **kwargs):
37116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return self.device.PushChangedFiles(*args, **kwargs)
38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  def GetSerialNumber(self):
40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return self.id
41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  def Install(self, *args, **kwargs):
43a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return self.device.old_interface.Install(*args, **kwargs)
44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  def GetInstallMetadata(self, apk_package):
46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    """Gets the metadata on the device for the apk_package apk."""
47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    # Matches lines like:
48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    # -rw-r--r-- system   system    7376582 2013-04-19 16:34 \
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    #   org.chromium.chrome.shell.apk
50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    # -rw-r--r-- system   system    7376582 2013-04-19 16:34 \
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    #   org.chromium.chrome.shell-1.apk
52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    apk_matcher = lambda s: re.match('.*%s(-[0-9]*)?.apk$' % apk_package, s)
53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    matches = filter(apk_matcher, self.install_metadata)
54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return matches[0] if matches else None
55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)def GetConfigurationForDevice(device_id):
58a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  device = device_utils.DeviceUtils(device_id)
59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  configuration = None
60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  has_root = False
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  is_online = device.IsOnline()
62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if is_online:
63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    cmd = 'ls -l /data/app; getprop ro.build.description'
64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    cmd_output = device.RunShellCommand(cmd)
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    has_root = not 'Permission denied' in cmd_output[0]
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if not has_root:
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      # Disable warning log messages from EnableRoot()
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      logging.getLogger().disabled = True
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      try:
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        device.EnableRoot()
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        has_root = True
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      except device_errors.CommandFailedError:
73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        has_root = False
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      finally:
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        logging.getLogger().disabled = False
76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      cmd_output = device.RunShellCommand(cmd)
77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    configuration = {
7923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        'id': device_id,
80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        'description': cmd_output[-1],
81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        'install_metadata': cmd_output[:-1],
82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      }
83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return configuration, is_online, has_root
84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochdef WriteConfigurations(configurations, path):
87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  # Currently we only support installing to the first device.
88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  build_utils.WriteJson(configurations[:1], path, only_if_changed=True)
89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochdef ReadConfigurations(path):
92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return build_utils.ReadJson(path)
93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochdef GetBuildDevice(configurations):
96eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  assert len(configurations) == 1
97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return BuildDevice(configurations[0])
98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochdef GetBuildDeviceFromPath(path):
101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  configurations = ReadConfigurations(path)
102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if len(configurations) > 0:
103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return GetBuildDevice(ReadConfigurations(path))
104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return None
105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
106