1# Copyright 2017 - The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15"""Provides class AdbMounter.
16
17The AdbMounter implements the abstract class BaseMounter. It can get files from
18a device which is connected by adb.
19"""
20
21import errno
22import logging
23import os
24import shutil
25import tempfile
26
27from gsi_util.mounters import base_mounter
28from gsi_util.utils import adb_utils
29
30
31class _AdbFileAccessor(base_mounter.BaseFileAccessor):
32  """Provides file access over an adb connection."""
33
34  def __init__(self, temp_dir, serial_num):
35    super(_AdbFileAccessor, self).__init__()
36    self._temp_dir = temp_dir
37    self._serial_num = serial_num
38
39  @staticmethod
40  def _make_parent_dirs(filename):
41    """Make parent directories as needed, no error if it exists."""
42    dir_path = os.path.dirname(filename)
43    try:
44      os.makedirs(dir_path)
45    except OSError as exc:
46      if exc.errno != errno.EEXIST:
47        raise
48
49  # override
50  def _handle_prepare_file(self, filename_in_storage):
51    filename = os.path.join(self._temp_dir, filename_in_storage)
52    logging.info('_AdbFileAccessor: Prepare file %s -> %s',
53                 filename_in_storage, filename)
54
55    self._make_parent_dirs(filename)
56    if not adb_utils.pull(filename, filename_in_storage, self._serial_num):
57      logging.info('  Fail to prepare file: %s', filename_in_storage)
58      return None
59
60    return base_mounter.MounterFile(filename)
61
62
63class AdbMounter(base_mounter.BaseMounter):
64  """Provides a file accessor which can access files by adb."""
65
66  def __init__(self, serial_num=None):
67    super(AdbMounter, self).__init__()
68    self._serial_num = serial_num
69    self._temp_dir = None
70
71  # override
72  def _handle_mount(self):
73    adb_utils.root(self._serial_num)
74
75    self._temp_dir = tempfile.mkdtemp()
76    logging.debug('Created temp dir: %s', self._temp_dir)
77
78    return _AdbFileAccessor(self._temp_dir, self._serial_num)
79
80  # override
81  def _handle_unmount(self):
82    if self._temp_dir:
83      logging.debug('Removing temp dir: %s', self._temp_dir)
84      shutil.rmtree(self._temp_dir)
85      self._temp_dir = None
86