device_api-android 1.0.1 → 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d7f064ddcac962170d4089858a6a791625388805
4
- data.tar.gz: 819b3797ef5b61c59383682c3758dcfa48ceb00d
3
+ metadata.gz: d056fdaa82d61147897272f7a3df98afd5f8e4af
4
+ data.tar.gz: ea866645ded8c453e60ac3baec01ee929d983c2e
5
5
  SHA512:
6
- metadata.gz: 819d33204b007a4ddfad07262978c0832f980287810d170e23f0034f7b8e06a203699bf98da9538a71d6549121a8de2e5010d29367120e3820ba090a0a923aef
7
- data.tar.gz: b55962d0d3e0511ea0877f4908c7d552916009b8d8ea43101ed16d90a2e656b58c5b67795766a2b4563fc502a850471408f9257ae42e2f8bfe52b7788edcc108
6
+ metadata.gz: 856ed8986cc089f9acc2098036a7e1deb95c93f86926f93bdbc2edd22f7cd5f5e4d7e255728049ee2d6321cde1910f54f810f1e3b5cdadba494385b86f9e40aa
7
+ data.tar.gz: 8b4a040ad4a5a01d652a7b1967ed3e1921726c5dcc1a6f916d76211616c465a9961607148e782f886444c245ac336127bf503c05b76684aa1d7ef1c2f1213caa
@@ -50,6 +50,8 @@ SUBSYSTEM=="usb", ATTR{idVendor}=="1949", ATTR{idProduct}=="000b", MODE="0666",
50
50
  SUBSYSTEM=="usb", ATTR{idVendor}=="1949", ATTR{idProduct}=="000c", MODE="0666", OWNER="hive"
51
51
  # Kindle Fire (Pink Case)
52
52
  SUBSYSTEM=="usb", ATTR{idVendor}=="1949", ATTR{idProduct}=="00f2", MODE="0666", OWNER="hive"
53
+ # Kindle Fire HDX 8.9 (3rd Generation) OS 4.5.5
54
+ SUBSYSTEM=="usb", ATTR{idVendor}=="1949", ATTR{idProduct}=="000d", mode="0666", OWNER="hive"
53
55
  # Sony Ericsson ST25i
54
56
  SUBSYSTEM=="usb", ATTR{idVendor}=="0fce", ATTR{idProduct}=="5171", MODE="0666", OWNER="hive"
55
57
  # Galaxy S2/S3
@@ -1,20 +1,21 @@
1
1
  GEM
2
2
  remote: https://rubygems.org/
3
3
  specs:
4
- device_api (1.0.0)
4
+ device_api (1.0.1)
5
5
  diff-lcs (1.2.5)
6
- rspec (3.0.0)
7
- rspec-core (~> 3.0.0)
8
- rspec-expectations (~> 3.0.0)
9
- rspec-mocks (~> 3.0.0)
10
- rspec-core (3.0.4)
11
- rspec-support (~> 3.0.0)
12
- rspec-expectations (3.0.4)
6
+ rspec (3.3.0)
7
+ rspec-core (~> 3.3.0)
8
+ rspec-expectations (~> 3.3.0)
9
+ rspec-mocks (~> 3.3.0)
10
+ rspec-core (3.3.1)
11
+ rspec-support (~> 3.3.0)
12
+ rspec-expectations (3.3.0)
13
13
  diff-lcs (>= 1.2.0, < 2.0)
14
- rspec-support (~> 3.0.0)
15
- rspec-mocks (3.0.4)
16
- rspec-support (~> 3.0.0)
17
- rspec-support (3.0.4)
14
+ rspec-support (~> 3.3.0)
15
+ rspec-mocks (3.3.1)
16
+ diff-lcs (>= 1.2.0, < 2.0)
17
+ rspec-support (~> 3.3.0)
18
+ rspec-support (3.3.0)
18
19
 
19
20
  PLATFORMS
20
21
  ruby
@@ -1,10 +1,10 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'device_api-android'
3
- s.version = '1.0.1'
3
+ s.version = '1.1.2'
4
4
  s.date = Time.now.strftime("%Y-%m-%d")
5
5
  s.summary = 'Android Device Management API'
6
6
  s.description = 'Android implementation of DeviceAPI'
7
- s.authors = ['BBC','David Buckhurst','Jitesh Gosai', 'Jon Wilson']
7
+ s.authors = ['David Buckhurst','Jitesh Gosai', 'Jon Wilson']
8
8
  s.email = 'david.buckhurst@bbc.co.uk'
9
9
  s.files = `git ls-files`.split "\n"
10
10
  s.homepage = 'https://github.com/bbc/device_api-android'
@@ -3,13 +3,21 @@ require 'device_api/android/adb'
3
3
  require 'device_api/android/device'
4
4
  require 'device_api/android/signing'
5
5
 
6
+ # Load plugins
7
+ require 'device_api/android/plugins/memory'
8
+ require 'device_api/android/plugins/battery'
9
+ require 'device_api/android/plugins/disk'
10
+
11
+ # Load additional device types
12
+ require 'device_api/android/device/kindle'
13
+
6
14
  module DeviceAPI
7
15
  module Android
8
16
  # Returns array of connected android devices
9
17
  def self.devices
10
18
  ADB.devices.map do |d|
11
19
  if d.keys.first && !d.keys.first.include?('?')
12
- DeviceAPI::Android::Device.new(serial: d.keys.first, state: d.values.first)
20
+ DeviceAPI::Android::Device.create( self.get_device_type(d.keys.first), { serial: d.keys.first, state: d.values.first } )
13
21
  end
14
22
  end
15
23
  end
@@ -20,7 +28,19 @@ module DeviceAPI
20
28
  raise DeviceAPI::BadSerialString.new("serial was '#{serial.nil? ? 'nil' : serial}'")
21
29
  end
22
30
  state = ADB.get_state(serial)
23
- DeviceAPI::Android::Device.new(serial: serial, state: state)
31
+ DeviceAPI::Android::Device.create( self.get_device_type(serial), { serial: serial, state: state })
32
+ end
33
+
34
+ # Return the device type used in determining which Device Object to create
35
+ def self.get_device_type(serial)
36
+ return :default if Device.new(serial: serial).manufacturer.nil?
37
+ case Device.new(serial: serial).manufacturer.downcase
38
+ when 'amazon'
39
+ type = :kindle
40
+ else
41
+ type = :default
42
+ end
43
+ type
24
44
  end
25
45
  end
26
46
 
@@ -26,23 +26,7 @@ module DeviceAPI
26
26
 
27
27
  fail result.stderr if result.exit != 0
28
28
 
29
- lines = result.stdout.split("\n")
30
- results = []
31
- lines.each do |l|
32
- if /(.*): (.*)/.match(l)
33
- # results.push(Regexp.last_match[1].strip => Regexp.last_match[2].strip)
34
- values = {}
35
-
36
- Regexp.last_match[2].strip.split(' ').each do |item| # split on an spaces
37
- item = item.to_s.tr('\'', '') # trim off any excess single quotes
38
- values[item.split('=')[0]] = item.split('=')[1] # split on the = and create a new hash
39
- end
40
-
41
- results << {Regexp.last_match[1].strip => values} # append the result tp new_result
42
-
43
- end
44
- end
45
- results
29
+ result.stdout.scan(/(.*): (.*)/).map { |a,b| { a => Hash[b.split(' ').map { |c| c.tr('\'','').split('=') }] } }
46
30
  end
47
31
 
48
32
  end
@@ -18,17 +18,7 @@ module DeviceAPI
18
18
  result = execute_with_timeout_and_retry('adb devices')
19
19
 
20
20
  raise ADBCommandError.new(result.stderr) if result.exit != 0
21
-
22
- lines = result.stdout.split("\n")
23
- results = []
24
-
25
- lines.shift # Drop the message line
26
- lines.each do |l|
27
- if /(.*)\t(.*)/.match(l)
28
- results.push(Regexp.last_match[1].strip => Regexp.last_match[2].strip)
29
- end
30
- end
31
- results
21
+ result.stdout.scan(/(.*)\t(.*)/).map { |a,b| {a => b}}
32
22
  end
33
23
 
34
24
  # Retrieve device state for a single device
@@ -54,13 +44,7 @@ module DeviceAPI
54
44
 
55
45
  lines = result.stdout.split("\n")
56
46
 
57
- props = {}
58
- lines.each do |l|
59
- if /\[(.*)\]:\s+\[(.*)\]/.match(l)
60
- props[Regexp.last_match[1]] = Regexp.last_match[2]
61
- end
62
- end
63
- props
47
+ process_dumpsys('\[(.*)\]:\s+\[(.*)\]', lines)
64
48
  end
65
49
 
66
50
  # Get the 'input' information from dumpsys
@@ -68,14 +52,7 @@ module DeviceAPI
68
52
  # @return (Hash) hash containing input information from dumpsys
69
53
  def self.getdumpsys(serial)
70
54
  lines = dumpsys(serial, 'input')
71
-
72
- props = {}
73
- lines.each do |l|
74
- if /(.*):\s+(.*)/.match(l)
75
- props[Regexp.last_match[1]] = Regexp.last_match[2]
76
- end
77
- end
78
- props
55
+ process_dumpsys('(.*):\s+(.*)', lines)
79
56
  end
80
57
 
81
58
  # Get the 'iphonesubinfo' from dumpsys
@@ -83,16 +60,52 @@ module DeviceAPI
83
60
  # @return (Hash) hash containing iphonesubinfo information from dumpsys
84
61
  def self.getphoneinfo(serial)
85
62
  lines = dumpsys(serial, 'iphonesubinfo')
63
+ process_dumpsys('(.*) =\s+(.*)', lines)
64
+ end
65
+
66
+ # Get the 'battery' information from dumpsys
67
+ # @param [String] serial serial number of device
68
+ # @return [Hash] hash containing battery information from dumpsys
69
+ def self.get_battery_info(serial)
70
+ lines = dumpsys(serial, 'battery')
71
+ process_dumpsys('(.*):\s+(.*)', lines)
72
+ end
86
73
 
74
+ # Processes the results from dumpsys to format them into a hash
75
+ # @param [String] regex_string regex string used to separate the results from the keys
76
+ # @param [Array] data data returned from dumpsys
77
+ # @return [Hash] hash containing the keys and values as distinguished by the supplied regex
78
+ def self.process_dumpsys(regex_string, data)
87
79
  props = {}
88
- lines.each do |l|
89
- if /(.*) =\s+(.*)/.match(l)
80
+ regex = Regexp.new(regex_string)
81
+ data.each do |line|
82
+ if regex.match(line)
90
83
  props[Regexp.last_match[1]] = Regexp.last_match[2]
91
84
  end
92
85
  end
86
+
93
87
  props
94
88
  end
95
89
 
90
+ # Get the 'power' information from dumpsys
91
+ # @param [String] serial serial number of device
92
+ # @return [Hash] hash containing power information from dumpsys
93
+ def self.getpowerinfo(serial)
94
+ lines = dumpsys(serial, 'power')
95
+ process_dumpsys('(.*)=(.*)', lines)
96
+ end
97
+
98
+ def self.get_device_dpi(serial)
99
+ lines = dumpsys(serial, 'window')
100
+ dpi = nil
101
+ lines.each do |line|
102
+ if /sw(\d*)dp/.match(line)
103
+ dpi = Regexp.last_match[1]
104
+ end
105
+ end
106
+ dpi
107
+ end
108
+
96
109
  # Returns the 'dumpsys' information from the specified device
97
110
  # @param serial serial number of device
98
111
  # @return (Array) array of results from adb shell dumpsys
@@ -108,18 +121,8 @@ module DeviceAPI
108
121
  # @option options [String] :serial serial number of device
109
122
  # @return (String) return result from adb install command
110
123
  def self.install_apk(options = {})
111
- apk = options[:apk]
112
- serial = options[:serial]
113
- result = execute("adb -s #{serial} install #{apk}")
114
-
115
- raise ADBCommandError.new(result.stderr) if result.exit != 0
116
-
117
- lines = result.stdout.split("\n").map { |line| line.strip }
118
- # lines.each do |line|
119
- # res=:success if line=='Success'
120
- # end
121
-
122
- lines.last
124
+ options[:action] = :install
125
+ change_apk(options)
123
126
  end
124
127
 
125
128
  # Uninstalls a specified package from a specified device
@@ -128,9 +131,27 @@ module DeviceAPI
128
131
  # @option options [String] :serial serial number of device
129
132
  # @return (String) return result from adb uninstall command
130
133
  def self.uninstall_apk(options = {})
134
+ options[:action] = :uninstall
135
+ change_apk(options)
136
+ end
137
+
138
+ def self.change_apk(options = {})
131
139
  package_name = options[:package_name]
140
+ apk = options[:apk]
132
141
  serial = options[:serial]
133
- result = execute("adb -s #{serial} uninstall #{package_name}")
142
+ action = options[:action]
143
+
144
+ case action
145
+ when :install
146
+ command = "adb -s #{serial} install #{apk}"
147
+ when :uninstall
148
+ command = "adb -s #{serial} uninstall #{package_name}"
149
+ else
150
+ raise ADBCommandError.new('No action specified')
151
+ end
152
+
153
+ result = execute(command)
154
+
134
155
  raise ADBCommandError.new(result.stderr) if result.exit != 0
135
156
 
136
157
  lines = result.stdout.split("\n").map { |line| line.strip }
@@ -203,6 +224,51 @@ module DeviceAPI
203
224
  execute(cmd)
204
225
  end
205
226
 
227
+ # Returns wifi status and access point name
228
+ # @param serial serial number of device
229
+ # @example
230
+ # DeviceAPI::ADB.wifi(serial)
231
+ def self.wifi(serial)
232
+ result = execute("adb -s #{serial} shell dumpsys wifi | grep mNetworkInfo")
233
+ if result.exit != 0
234
+ raise ADBCommandError.new(result.stderr)
235
+ else
236
+ result = {:status => result.stdout.match("state:(.*?),")[1].strip, :access_point => result.stdout.match("extra:(.*?),")[1].strip.gsub(/"/,'')}
237
+ end
238
+ result
239
+ end
240
+
241
+ # Sends a key event to the specified device
242
+ # @param [String] serial serial number of device
243
+ # @param [String] keyevent keyevent to send to the device
244
+ def self.keyevent(serial, keyevent)
245
+ result = execute("adb -s #{serial} shell input keyevent #{keyevent}")
246
+ raise ADBCommandError.new(result.stderr) if result.exit != 0
247
+ end
248
+
249
+ # Sends a swipe command to the specified device
250
+ # @param [String] serial serial number of the device
251
+ # @param [Hash] coords hash of coordinates to swipe from / to
252
+ # @option coords [String] :x_from (0) Coordinate to start from on the X axis
253
+ # @option coords [String] :x_to (0) Coordinate to end on on the X axis
254
+ # @option coords [String] :y_from (0) Coordinate to start from on the Y axis
255
+ # @option coords [String] :y_to (0) Coordinate to end on on the Y axis
256
+ def self.swipe(serial, coords = {x_from: 0, x_to: 0, y_from: 0, y_to: 0 })
257
+ execute("adb -s #{serial} shell input swipe #{coords[:x_from]} #{coords[:x_to]} #{coords[:y_from]} #{coords[:y_to]}")
258
+ raise ADBCommandError.new(result.stderr) if result.exit != 0
259
+ end
260
+
261
+ # Starts intent using adb
262
+ # Returns stdout
263
+ # @param serial serial number of device
264
+ # @param command -option activity
265
+ # @example
266
+ # DeviceAPI::ADB.am(serial, "-a android.intent.action.MAIN -n com.android.settings/.wifi.WifiSettings")
267
+ def self.am(serial, command)
268
+ result = execute("adb -s #{serial} shell am start #{command}")
269
+ raise ADBCommandError.new(result.stderr) if result.exit != 0
270
+ return result.stdout
271
+ end
206
272
  end
207
273
 
208
274
  # ADB Error class
@@ -9,6 +9,21 @@ module DeviceAPI
9
9
  module Android
10
10
  # Device class used for containing the accessors of the physical device information
11
11
  class Device < DeviceAPI::Device
12
+
13
+ @@subclasses; @@subclasses = {}
14
+
15
+ # Called by any inheritors to register themselves with the parent class
16
+ def self.inherited(klass)
17
+ key = /::([^:]+)$/.match(klass.to_s.downcase)[1].to_sym
18
+ @@subclasses[key] = klass
19
+ end
20
+
21
+ # Returns an object of the specified type, if it exists. Defaults to returning self
22
+ def self.create(type, options = {} )
23
+ return @@subclasses[type.to_sym].new(options) if @@subclasses[type.to_sym]
24
+ return self.new(options)
25
+ end
26
+
12
27
  def initialize(options = {})
13
28
  @serial = options[:serial]
14
29
  @state = options[:state]
@@ -58,13 +73,25 @@ module DeviceAPI
58
73
  get_prop('ro.build.version.release')
59
74
  end
60
75
 
76
+ # Return the battery level
77
+ # @return (String) device battery level
78
+ def battery_level
79
+ get_battery_info['level']
80
+ end
81
+
82
+ # Is the device currently being powered?
83
+ # @return (Boolean) true if it is being powered in some way, false if it is unpowered
84
+ def powered?
85
+ !get_battery_info.select { |keys| keys.include?('powered')}.select { |_,v| v == 'true' }.empty?
86
+ end
87
+
61
88
  # Return the device orientation
62
89
  # @return (String) current device orientation
63
90
  def orientation
64
91
  res = get_dumpsys('SurfaceOrientation')
65
92
 
66
93
  case res
67
- when '0'
94
+ when '0','2'
68
95
  :portrait
69
96
  when '1', '3'
70
97
  :landscape
@@ -141,8 +168,94 @@ module DeviceAPI
141
168
  get_phoneinfo['Device ID']
142
169
  end
143
170
 
171
+ # Get the memory information for the current device
172
+ # @return [DeviceAPI::Android::Plugins::Memory] the memory plugin containing relevant information
173
+ def memory
174
+ get_memory_info
175
+ end
176
+
177
+ def battery
178
+ get_battery_info
179
+ end
180
+
181
+ # Check if the devices screen is currently turned on
182
+ # @return [Boolean] true if the screen is on, otherwise false
183
+ def screen_on?
184
+ return true if get_powerinfo['mScreenOn'].to_s.downcase == 'true'
185
+ false
186
+ end
187
+
188
+ # Unlock the device by sending a wakeup command
189
+ def unlock
190
+ ADB.keyevent(serial, '26') unless screen_on?
191
+ end
192
+
193
+ # Return the DPI of the attached device
194
+ # @return [String] DPI of attached device
195
+ def dpi
196
+ get_dpi(serial)
197
+ end
198
+
199
+ # Return the device type based on the DPI
200
+ # @return [Symbol] :tablet or :mobile based upon the devices DPI
201
+ def type
202
+ if get_dpi.to_i > 533
203
+ :tablet
204
+ else
205
+ :mobile
206
+ end
207
+ end
208
+
209
+ # Returns wifi status and access point name
210
+ # @return [Hash] :status and :access_point
211
+ def wifi_status
212
+ ADB.wifi(serial)
213
+ end
214
+
215
+ def battery_info
216
+ ADB.get_battery_info(serial)
217
+ end
218
+
219
+ # @param [String] command to start the intent
220
+ # Return the stdout of executed intent
221
+ # @return [String] stdout
222
+ def start_intent(command)
223
+ ADB.am(serial,command)
224
+ end
225
+
226
+ #Reboots the device
227
+ def reboot
228
+ ADB.reboot(serial)
229
+ end
230
+
231
+ # Returns disk status
232
+ # @return [Hash] containing disk statistics
233
+ def diskstat
234
+ get_disk_info
235
+ end
236
+
237
+ # Returns the device uptime
238
+ def uptime
239
+ ADB.get_uptime(serial)
240
+ end
241
+
144
242
  private
145
243
 
244
+ def get_disk_info
245
+ @diskstat = DeviceAPI::Android::Plugin::Disk.new(serial: serial) unless @diskstat
246
+ @diskstat.process_stats
247
+ end
248
+
249
+ def get_battery_info
250
+ @battery = DeviceAPI::Android::Plugin::Battery.new(serial: serial) unless @battery
251
+ @battery
252
+ end
253
+
254
+ def get_memory_info
255
+ @memory = DeviceAPI::Android::Plugin::Memory.new(serial: serial) unless @memory
256
+ @memory
257
+ end
258
+
146
259
  def get_app_props(key)
147
260
  unless @app_props
148
261
  @app_props = AAPT.get_app_props(@apk)
@@ -162,6 +275,11 @@ module DeviceAPI
162
275
  @props[key]
163
276
  end
164
277
 
278
+ def get_powerinfo
279
+ ADB.getpowerinfo(serial)
280
+ end
281
+
282
+
165
283
  def get_phoneinfo
166
284
  ADB.getphoneinfo(serial)
167
285
  end
@@ -173,6 +291,10 @@ module DeviceAPI
173
291
  def uninstall_apk(package_name)
174
292
  ADB.uninstall_apk(package_name: package_name, serial: serial)
175
293
  end
294
+
295
+ def get_dpi
296
+ ADB.get_device_dpi(serial)
297
+ end
176
298
  end
177
299
  end
178
300
  end
@@ -0,0 +1,14 @@
1
+ module DeviceAPI
2
+ module Android
3
+ # Kindle specific device class
4
+ class Kindle < Device
5
+ # On non-Kindle devices, if a device is locked without a password (i.e. 'Swipe to unlock'), then
6
+ # you can unlock that device by broadcasting a 'WakeUp' intent. On Kindle devices, this does not
7
+ # work due to Amazons implementation of the Keyguard.
8
+ def unlock
9
+ ADB.keyevent(serial, '26') unless screen_on?
10
+ ADB.swipe(serial, { x_from: 900, x_to: 300, y_from: 100, y_to: 100 } )
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,22 @@
1
+ module DeviceAPI
2
+ module Android
3
+ module Plugin
4
+ class Battery
5
+ attr_reader :current_temp, :max_temp, :max_current, :voltage, :level, :health, :status
6
+
7
+ def initialize(options = {})
8
+ serial = options[:serial]
9
+ props = ADB.get_battery_info(serial)
10
+ @current_temp = props["temperature"]
11
+ @max_temp = props["mBatteryMaxTemp"]
12
+ @max_current = props["mBatteryMaxCurrent"]
13
+ @voltage = props["voltage"]
14
+ @level = props["level"]
15
+ @health = props["health"]
16
+ @status = props["status"]
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+
@@ -0,0 +1,29 @@
1
+ module DeviceAPI
2
+ module Android
3
+ module Plugin
4
+ class Disk
5
+
6
+ attr_reader :serial
7
+ def initialize(options = {})
8
+ @serial = options[:serial]
9
+ end
10
+
11
+ def process_stats(options = {})
12
+ disk_info = {}
13
+ stats = options[:data] || ADB.dumpsys(@serial, 'diskstats')
14
+ stats.each do |stat|
15
+ if /(.*)-.*:\s(.*)\s\/\s([0-9]*[A-Z])\s[a-z]*\s=\s([0-9]*%)/.match(stat)
16
+ disk_info["#{Regexp.last_match[1].downcase}_total"] = Regexp.last_match[3]
17
+ disk_info["#{Regexp.last_match[1].downcase}_free"] = Regexp.last_match[4]
18
+ disk_info["#{Regexp.last_match[1].downcase}_used"] = Regexp.last_match[2]
19
+ elsif /(.*):\s(\S*)/.match(stat)
20
+ disk_info[Regexp.last_match[1].downcase] = Regexp.last_match[2]
21
+ end
22
+ end
23
+ disk_info
24
+ end
25
+
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,77 @@
1
+ module DeviceAPI
2
+ module Android
3
+ # Plugins contain extra information about the attached device(s)
4
+ module Plugin
5
+ # Class used to provide information about process memory usage
6
+ # and device memory usage
7
+ class Memory
8
+
9
+ # Class used for holding process information
10
+ class MemInfo
11
+ attr_reader :process, :memory, :pid
12
+ def initialize(options = {})
13
+ @process = options[:process]
14
+ @memory = options[:memory]
15
+ @pid = options[:pid]
16
+ end
17
+ end
18
+
19
+ # Class used for storing process information
20
+ class RAM
21
+ attr_accessor :total, :free, :used, :lost, :tuning
22
+ def initialize(options = {})
23
+ @total = options[:total]
24
+ @free = options[:free]
25
+ @used = options[:used]
26
+ @lost = options[:lost]
27
+ @tuning = options[:tuning]
28
+ end
29
+ end
30
+
31
+ attr_accessor :processes, :mem_info
32
+
33
+ def initialize(options = {})
34
+ @serial = options[:serial]
35
+ info = options[:data] || ADB.dumpsys(@serial, 'meminfo')
36
+ process_data(info)
37
+ end
38
+
39
+ def process_data(memory_info)
40
+ groups = memory_info.chunk { |a| a == '' }.reject { |a,_| a }.map { |_,b| b }
41
+
42
+ raise 'A different ADB result has been received' unless groups[1].first == 'Total PSS by process:'
43
+ @processes = []
44
+ process_total_pss_by_process(groups[1])
45
+ process_ram_info(groups[4])
46
+ end
47
+
48
+ def update
49
+ meminfo = ADB.dumpsys(@serial, 'meminfo')
50
+ process_data(meminfo)
51
+ end
52
+
53
+ # Processes memory used by each running process
54
+ def process_total_pss_by_process(data)
55
+ data.each do |l|
56
+ if /(.*):\s+(.*)\s+\(.*pid\s+(\S*).*\)/.match(l)
57
+ @processes << MemInfo.new(process: Regexp.last_match[2], memory: Regexp.last_match[1], pid: Regexp.last_match[3] )
58
+ end
59
+ end
60
+ end
61
+
62
+ # Processes memory used by the device
63
+ def process_ram_info(data)
64
+ ram_info = {}
65
+ data.each do |l|
66
+ if /Tuning:\s+(.*)/.match(l)
67
+ ram_info['tuning'] = Regexp.last_match[1]
68
+ elsif /(.*):\s(-?[0-9]*\s\S*)/.match(l)
69
+ ram_info[Regexp.last_match[1].downcase] = Regexp.last_match[2]
70
+ end
71
+ end
72
+ @mem_info = RAM.new(total: ram_info['total ram'], free: ram_info['free ram'], used: ram_info['used ram'], lost: ram_info['lost'], tuning: ram_info['tuning'])
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -54,7 +54,7 @@ module DeviceAPI
54
54
  # @param [String] apk_path full path to apk to check
55
55
  # @return returns false if the apk is unsigned, true if it is signed
56
56
  def self.is_apk_signed?(apk_path)
57
- result = execute("aapt list #{apk_path} | grep '^META-INF.*\.RSA$'")
57
+ result = execute("aapt list #{apk_path} | grep '^META-INF\/.*'")
58
58
  return false if result.stdout.empty?
59
59
  true
60
60
  end
@@ -63,7 +63,7 @@ module DeviceAPI
63
63
  # @param [String] apk_path full path to the apk
64
64
  # @return [Boolean, Exception] returns true if the apk is successfully unsigned, otherwise an exception is raised
65
65
  def self.unsign_apk(apk_path)
66
- file_list = execute("aapt list #{apk_path} | grep '^META-INF.*\.RSA$'")
66
+ file_list = execute("aapt list #{apk_path} | grep '^META-INF\/.*'")
67
67
  result = execute("aapt remove #{apk_path} #{file_list.stdout.split(/\s+/).join(' ')}")
68
68
  raise SigningCommandError.new(result.stderr) if result.exit != 0
69
69
  true
@@ -135,4 +135,23 @@ _______________________________________________________
135
135
  end
136
136
  end
137
137
 
138
+ describe ".wifi" do
139
+ it "returns wifi info" do
140
+ out= <<_______________________________________________________
141
+ mNetworkInfo [type: WIFI[], state: CONNECTED/CONNECTED, reason: (unspecified), extra: "TVMP-DevNet", roaming: false, failover: false, isAvailable: true, isConnectedToProvisioningNetwork: false]
142
+ _______________________________________________________
143
+ allow(Open3).to receive(:capture3) { [out, '', $STATUS_ZERO] }
144
+ expect( DeviceAPI::Android::ADB.wifi('12345').class).to eq(Hash)
145
+ end
146
+ end
147
+
148
+ describe ".am" do
149
+ it "returns the stdout" do
150
+ out= <<_______________________________________________________
151
+ Starting: Intent { act=android.intent.action.MAIN cmp=com.android.settings/.wifi.WifiSettings }
152
+ _______________________________________________________
153
+ allow(Open3).to receive(:capture3) { [out, '', $STATUS_ZERO] }
154
+ expect( DeviceAPI::Android::ADB.am('03157df373208426' ,'12345').class).to eq(String)
155
+ end
156
+ end
138
157
  end
@@ -7,7 +7,7 @@ describe DeviceAPI::Android do
7
7
 
8
8
  it 'Returns an empty array when no devices are connected' do
9
9
  out = <<_______________________________________________________
10
- List of devices attached
10
+ List of devices attached
11
11
 
12
12
  _______________________________________________________
13
13
  allow(Open3).to receive(:capture3) { [out, '', $STATUS_ZERO] }
@@ -16,8 +16,8 @@ _______________________________________________________
16
16
 
17
17
  it "returns an array with a single item when there's one device attached" do
18
18
  out = <<_______________________________________________________
19
- List of devices attached
20
- SH34RW905290 device
19
+ List of devices attached
20
+ SH34RW905290 device
21
21
 
22
22
  _______________________________________________________
23
23
  allow(Open3).to receive(:capture3) { [out, '', $STATUS_ZERO] }
metadata CHANGED
@@ -1,17 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: device_api-android
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.2
5
5
  platform: ruby
6
6
  authors:
7
- - BBC
8
7
  - David Buckhurst
9
8
  - Jitesh Gosai
10
9
  - Jon Wilson
11
10
  autorequire:
12
11
  bindir: bin
13
12
  cert_chain: []
14
- date: 2015-05-22 00:00:00.000000000 Z
13
+ date: 2015-10-06 00:00:00.000000000 Z
15
14
  dependencies:
16
15
  - !ruby/object:Gem::Dependency
17
16
  name: device_api
@@ -64,7 +63,10 @@ files:
64
63
  - lib/device_api/android/aapt.rb
65
64
  - lib/device_api/android/adb.rb
66
65
  - lib/device_api/android/device.rb
67
- - lib/device_api/android/devices/default.rb
66
+ - lib/device_api/android/device/kindle.rb
67
+ - lib/device_api/android/plugins/battery.rb
68
+ - lib/device_api/android/plugins/disk.rb
69
+ - lib/device_api/android/plugins/memory.rb
68
70
  - lib/device_api/android/signing.rb
69
71
  - spec/adb_spec.rb
70
72
  - spec/android_device_spec.rb
@@ -90,9 +92,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
90
92
  version: '0'
91
93
  requirements: []
92
94
  rubyforge_project:
93
- rubygems_version: 2.4.5
95
+ rubygems_version: 2.4.8
94
96
  signing_key:
95
97
  specification_version: 4
96
98
  summary: Android Device Management API
97
99
  test_files: []
98
- has_rdoc:
File without changes