content_settings.py revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
1# Copyright 2014 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
5
6class ContentSettings(dict):
7
8  """A dict interface to interact with device content settings.
9
10  System properties are key/value pairs as exposed by adb shell content.
11  """
12
13  def __init__(self, table, device):
14    super(ContentSettings, self).__init__()
15    sdk_version_string = device.old_interface.system_properties[
16        'ro.build.version.sdk']
17    try:
18      sdk_version = int(sdk_version_string)
19      assert sdk_version >= 16, (
20          'ContentSettings supported only on SDK 16 and later')
21    except ValueError:
22      assert False, ('Unknown SDK version %s' % sdk_version_string)
23    self._table = table
24    self._device = device
25
26  @staticmethod
27  def _GetTypeBinding(value):
28    if isinstance(value, bool):
29      return 'b'
30    if isinstance(value, float):
31      return 'f'
32    if isinstance(value, int):
33      return 'i'
34    if isinstance(value, long):
35      return 'l'
36    if isinstance(value, str):
37      return 's'
38    raise ValueError('Unsupported type %s' % type(value))
39
40  def iteritems(self):
41    # Example row:
42    # 'Row: 0 _id=13, name=logging_id2, value=-1fccbaa546705b05'
43    for row in self._device.RunShellCommand(
44        'content query --uri content://%s' % self._table, root=True):
45      fields = row.split(', ')
46      key = None
47      value = None
48      for field in fields:
49        k, _, v = field.partition('=')
50        if k == 'name':
51          key = v
52        elif k == 'value':
53          value = v
54      assert key, value
55      yield key, value
56
57  def __getitem__(self, key):
58    return self._device.RunShellCommand(
59        'content query --uri content://%s --where "name=\'%s\'" '
60        '--projection value' % (self._table, key), root=True).strip()
61
62  def __setitem__(self, key, value):
63    if key in self:
64      self._device.RunShellCommand(
65          'content update --uri content://%s '
66          '--bind value:%s:%s --where "name=\'%s\'"' % (
67              self._table,
68              self._GetTypeBinding(value), value, key),
69          root=True)
70    else:
71      self._device.RunShellCommand(
72          'content insert --uri content://%s '
73          '--bind name:%s:%s --bind value:%s:%s' % (
74              self._table,
75              self._GetTypeBinding(key), key,
76              self._GetTypeBinding(value), value),
77          root=True)
78
79  def __delitem__(self, key):
80    self._device.RunShellCommand(
81        'content delete --uri content://%s '
82        '--bind name:%s:%s' % (
83            self._table,
84            self._GetTypeBinding(key), key),
85        root=True)
86