capsule: Add settings to config, more reserved words.

Allow the user to decide if capsule should lock the phone to portrait
mode and if it should clear notifications (to make the screenshots a
little nicer) and split up the config file into sections.  Also, add a
group of words associated with already being registered for an app to
the list so that Views with these words in the text or id are clicked on
last.

Change-Id: Ic33d656510ed2bca05f618aea5e041df6c0aa852
diff --git a/capsule/README.md b/capsule/README.md
index 7563c78..9e5390a 100644
--- a/capsule/README.md
+++ b/capsule/README.md
@@ -114,7 +114,7 @@
 
 To modify the file without Git tracking it, type
 
-``$ git update-index --assume-unchanged <file>``
+``$ git update-index --assume-unchanged config.ini``
 
 ## Contributors
 
diff --git a/capsule/capsule.py b/capsule/capsule.py
index b163a6d..ceea28f 100644
--- a/capsule/capsule.py
+++ b/capsule/capsule.py
@@ -97,14 +97,6 @@
     print HELP_MSG
     sys.exit()
 
-    # Lock phone orientation to portrait.
-    # Turn off automatic rotation.
-    device.shell('content insert --uri content://settings/system --bind '
-                 'name:s:accelerometer_rotation --bind value:i:0')
-    # Rotate to portrait mode.
-    device.shell('content insert --uri content://settings/system --bind '
-                 'name:s:user_rotation --bind value:i:0')
-
   # User only specified emulator name or nothing at all.
   if len(sys.argv) <= 2:
     print 'No command line arguments, crawling currently launched app.'
diff --git a/capsule/config.ini b/capsule/config.ini
index 6d81280..4358a0b 100644
--- a/capsule/config.ini
+++ b/capsule/config.ini
@@ -1,6 +1,11 @@
-[basic info]
+[settings]
+lock_portrait_mode = True
+clear_notifications = True
+
+[basic_info]
 first_name = Jane
 last_name = Smith
+username = capsulecrawler33
 email = foo@bar.com
 password = DefaultPw1!
 zipcode = 94109
diff --git a/capsule/config.py b/capsule/config.py
index 057df90..6446c73 100644
--- a/capsule/config.py
+++ b/capsule/config.py
@@ -23,5 +23,6 @@
     parser = SafeConfigParser()
     parser.read(CONFIG_FILE)
     for section_name in parser.sections():
+      self.data[section_name] = {}
       for name, value in parser.items(section_name):
-        self.data[name] = value
+        self.data[section_name][name] = value
diff --git a/capsule/crawlpkg.py b/capsule/crawlpkg.py
index 1fde7f0..3b3312d 100644
--- a/capsule/crawlpkg.py
+++ b/capsule/crawlpkg.py
@@ -54,6 +54,12 @@
 
 NEGATIVE_WORDS = ['no', 'cancel', 'back', 'neg' 'deny', 'prev', 'exit',
                   'delete', 'end', 'remove', 'clear', 'reset', 'undo']
+# It's ok if the registered words also include the name of a social network
+# (i.e. "Sign in with Google") and sends that view to the end of the list
+# because the program will still go through the list of all clickable views
+# looking for the social network logins.
+REGISTERED_WORDS = ['sign in', 'log', 'already', 'member']
+END_WORDS = NEGATIVE_WORDS + REGISTERED_WORDS
 
 
 def extract_between(text, sub1, sub2, nth=1):
@@ -166,36 +172,39 @@
     perform_press_back(device)
     return
 
-  # Check if the id contains any of the words in the [basic info] section of the
+  # Check if the id contains any of the words in the [basic_info] section of the
   # config. If any of these fields have been removed, do not type anything.
+  basic_info = config_data.get('basic_info')
   if 'name' in prev_clicked:
     if any(x in prev_clicked for x in['last', 'sur']):
-      print 'Typing last name ' + config_data.get('last_name', '')
-      device.type(config_data.get('last_name', ''))
+      print 'Typing last name ' + basic_info.get('last_name', '')
+      device.type(basic_info.get('last_name', ''))
+    elif any(x in prev_clicked for x in['user']):
+      print 'Typing username ' + basic_info.get('username', '')
     else:
-      print 'Typing first name ' + config_data.get('first_name', '')
-      device.type(config_data.get('first_name', ''))
+      print 'Typing first name ' + basic_info.get('first_name', '')
+      device.type(basic_info.get('first_name', ''))
   elif any(x in prev_clicked for x in['email', 'mail', 'address']):
-    print 'Typing email address ' + config_data.get('email', '')
-    device.type(config_data.get('email', ''))
+    print 'Typing email address ' + basic_info.get('email', '')
+    device.type(basic_info.get('email', ''))
   elif any(x in prev_clicked for x in['password', 'pw']):
-    print 'Typing password ' + config_data.get('password', '')
-    device.type(config_data.get('password', ''))
+    print 'Typing password ' + basic_info.get('password', '')
+    device.type(basic_info.get('password', ''))
   elif any(x in prev_clicked for x in['zip']):
-    print 'Typing zip code ' + config_data.get('zipcode', '')
-    device.type(config_data.get('zipcode', ''))
+    print 'Typing zip code ' + basic_info.get('zipcode', '')
+    device.type(basic_info.get('zipcode', ''))
   elif any(x in prev_clicked for x in['phone']):
-    print 'Typing phone number ' + config_data.get('phone_num', '')
-    device.type(config_data.get('phone_num', ''))
+    print 'Typing phone number ' + basic_info.get('phone_num', '')
+    device.type(basic_info.get('phone_num', ''))
   else:
     # If the user has added additional fields in the config, check for those.
-    for c in config_data:
+    for c in config_data.get('extra'):
       if any(x in prev_clicked for x in c):
-        device.type(config_data.get(c, ''))
+        device.type(config_data.get('extra').get(c, ''))
         break
     else:
-      print 'Typing default text ' + config_data.get('default', '')
-      device.type(config_data.get('default', ''))
+      print 'Typing default text ' + basic_info.get('default', '')
+      device.type(basic_info.get('default', ''))
 
   # TODO(afergan): The enter key can sometimes advance us to the next field or
   # Layout, but we would have to track that here. For now, just minimize the
@@ -575,7 +584,7 @@
     if clickview.getText():
       print 'Text: ' + clickview.getText()
       clickstr += ' ' + clickview.getText().lower()
-    if any(x in clickstr for x in NEGATIVE_WORDS):
+    if any(x in clickstr for x in END_WORDS):
       print 'Going to the end of the list b/c of text or ID: ' + clickstr
       l.clickable.remove(clickview)
       l.clickable.append(clickview)
@@ -917,6 +926,23 @@
   layout_graph = {}
 
   config_data = Config().data
+  settings = config_data.get('settings')
+
+  if settings:
+    if settings.get('lock_portrait_mode'):
+      # TODO(afergan): Is this best to do after each app (in case an app changes
+      # the phone's settings) or just run when we start the program?
+
+      # Lock phone orientation to portrait.
+      # Turn off automatic rotation.
+      device.shell('content insert --uri content://settings/system --bind '
+                   'name:s:accelerometer_rotation --bind value:i:0')
+      # Rotate to portrait mode.
+      device.shell('content insert --uri content://settings/system --bind '
+                   'name:s:user_rotation --bind value:i:0')
+    if settings.get('clear_notifications'):
+      # Clear all notifications.
+      device.shell('su 0 service call notification 1')
 
   # Stores if we have logged in during this crawl/session. If the app has
   # previously logged into an app or service (and can skip the authorization
@@ -975,6 +1001,7 @@
     starting_layout = obtain_curr_layout(activity, package_name, vc_dump,
                                          layout_map, still_exploring, device)
     starting_layout.depth = 0
+    print 'Starting layout: ' + starting_layout.get_name()
     path = find_shortest_path(layout_graph, starting_layout.get_name(),
                               l.get_name())
     if path: