Implements bluetooth test checking that contact details have been
imported correctly from the connected device.
Test: https://paste.googleplex.com/6695844559454208
Bug: 273366005
Change-Id: I36a280ad4f9befe98045f5b9cbe202b3bb78251f
diff --git a/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoDialHelper.java b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoDialHelper.java
index 2d47492..c657ddb 100644
--- a/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoDialHelper.java
+++ b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoDialHelper.java
@@ -218,6 +218,13 @@
String getFirstContactFromContactList();
/**
+ * Setup expectations: A Contact details page is open.
+ *
+ * <p>This method is used to get the home address from the currently-open contact.
+ */
+ String getHomeAddress();
+
+ /**
* Setup expectations: The app is open.
*
* <p>This method is used to verify if a contact is added to Favorites.
@@ -248,6 +255,14 @@
void openContacts();
/**
+ * Setup expectations: The contacts page is open.
+ *
+ * <p>This method is used to open the contact details page of the first visible contact. Throws
+ * an error if no contacts are visible.
+ */
+ void openFirstContactDetails();
+
+ /**
* Setup expectations: The app is open and there is an ongoing call.
*
* <p>This method is used check if ongoing call is displayed on home.
diff --git a/libraries/automotive-helpers/auto-default-config/resources/assets/defaultSpectatioConfig.json b/libraries/automotive-helpers/auto-default-config/resources/assets/defaultSpectatioConfig.json
index 9e6d41c..af57dba 100644
--- a/libraries/automotive-helpers/auto-default-config/resources/assets/defaultSpectatioConfig.json
+++ b/libraries/automotive-helpers/auto-default-config/resources/assets/defaultSpectatioConfig.json
@@ -199,11 +199,43 @@
"VALUE": "title",
"PACKAGE": "com.android.car.dialer"
},
+ "CONTACT_ADDRESS": {
+ "TYPE": "RESOURCE_ID",
+ "VALUE": "title",
+ "PACKAGE": "com.android.car.dialer"
+ },
+ "CONTACT_HOME_ADDRESS": {
+ "TYPE": "MULTIPLE",
+ "SPECIFIERS": [
+ {
+ "TYPE": "RESOURCE_ID",
+ "VALUE": "title"
+ },
+ {
+ "TYPE": "HAS_ANCESTOR",
+ "MAX_DEPTH": 1,
+ "ANCESTOR": {
+ "TYPE": "HAS_DESCENDANT",
+ "MAX_DEPTH": 1,
+ "DESCENDANT": {
+ "TYPE": "TEXT",
+ "VALUE": "Home"
+ }
+ }
+ }
+
+ ]
+ },
"CONTACT_DETAIL": {
"TYPE": "RESOURCE_ID",
"VALUE": "show_contact_detail_id",
"PACKAGE": "com.android.car.dialer"
},
+ "CONTACT_DETAILS_PAGE": {
+ "TYPE": "DESCRIPTION",
+ "VALUE": "com.android.car.ui.utils.ROTARY_CONTAINER"
+ },
+
"CALL_HISTORY_INFO": {
"TYPE": "RESOURCE_ID",
"VALUE": "call_action_id",
diff --git a/libraries/automotive-helpers/auto-default-config/src/android/platform/helpers/AutomotiveConfigConstants.java b/libraries/automotive-helpers/auto-default-config/src/android/platform/helpers/AutomotiveConfigConstants.java
index 75f1668..0763056 100644
--- a/libraries/automotive-helpers/auto-default-config/src/android/platform/helpers/AutomotiveConfigConstants.java
+++ b/libraries/automotive-helpers/auto-default-config/src/android/platform/helpers/AutomotiveConfigConstants.java
@@ -55,6 +55,12 @@
public static final String SORT_BY_LAST_NAME = "SORT_BY_LAST_NAME";
public static final String CONTACTS_MENU = "CONTACTS_MENU";
public static final String CONTACT_NAME = "CONTACT_NAME";
+
+ public static final String CONTACT_ADDRESS = "CONTACT_ADDRESS";
+
+ public static final String CONTACT_HOME_ADDRESS = "CONTACT_HOME_ADDRESS";
+
+ public static final String CONTACT_DETAILS_PAGE = "CONTACT_DETAILS_PAGE";
public static final String CONTACT_DETAIL = "CONTACT_DETAIL";
public static final String CALL_HISTORY_INFO = "CALL_HISTORY_INFO";
public static final String SEARCH_CONTACT = "SEARCH_CONTACT";
diff --git a/libraries/automotive-helpers/dial-app-helper/src/android/platform/helpers/DialHelperImpl.java b/libraries/automotive-helpers/dial-app-helper/src/android/platform/helpers/DialHelperImpl.java
index 92c02c3..d8ade89 100644
--- a/libraries/automotive-helpers/dial-app-helper/src/android/platform/helpers/DialHelperImpl.java
+++ b/libraries/automotive-helpers/dial-app-helper/src/android/platform/helpers/DialHelperImpl.java
@@ -45,6 +45,7 @@
private BySelector mForwardButtonSelector;
private BySelector mScrollableElementSelector;
private ScrollDirection mScrollDirection;
+ private UiObject2 mHomeAddress;
public DialHelperImpl(Instrumentation instr) {
super(instr);
@@ -454,6 +455,7 @@
}
/** {@inheritDoc} */
+ @Override
public boolean isContactInFavorites(String contact) {
openFavorites();
UiObject2 uiObject = getSpectatioUiUtil().findUiObject(contact);
@@ -529,6 +531,32 @@
getSpectatioUiUtil().clickAndWait(contactDetailButton);
}
+ /** {@inheritDoc} */
+ @Override
+ public String getHomeAddress() {
+
+ BySelector homeAddressSelector =
+ getUiElementFromConfig(AutomotiveConfigConstants.CONTACT_HOME_ADDRESS);
+
+ BySelector detailsScrollableSelector =
+ getUiElementFromConfig(AutomotiveConfigConstants.CONTACT_DETAILS_PAGE);
+
+ UiObject2 homeAddress =
+ mScrollUtility.scrollAndFindUiObject(
+ mScrollAction,
+ mScrollDirection,
+ mForwardButtonSelector,
+ mBackwardButtonSelector,
+ detailsScrollableSelector,
+ homeAddressSelector,
+ String.format("scroll to find home address."));
+
+ getSpectatioUiUtil()
+ .validateUiObject(homeAddress, AutomotiveConfigConstants.CONTACT_HOME_ADDRESS);
+
+ return homeAddress.getText();
+ }
+
/** This method is used to get the first history in the Recents tab. */
private UiObject2 getCallHistory() {
BySelector callHistorySelector =
@@ -550,6 +578,16 @@
getSpectatioUiUtil().clickAndWait(contactMenuButton);
}
+ /** This method opens the details page of the first contact on the page. */
+ public void openFirstContactDetails() {
+ BySelector contactDetailsSelector =
+ getUiElementFromConfig(AutomotiveConfigConstants.CONTACT_DETAIL);
+ UiObject2 contactDetailButton = getSpectatioUiUtil().findUiObject(contactDetailsSelector);
+ getSpectatioUiUtil()
+ .validateUiObject(contactDetailButton, AutomotiveConfigConstants.CONTACT_DETAIL);
+ getSpectatioUiUtil().clickAndWait(contactDetailButton);
+ }
+
/** This method opens the contact search window. */
private void openSearchContact() {
BySelector searchContactSelector =
diff --git a/tests/automotive/mobly_tests/dialer/Android.bp b/tests/automotive/mobly_tests/dialer/Android.bp
index 4bcb6cb..ec15b67 100644
--- a/tests/automotive/mobly_tests/dialer/Android.bp
+++ b/tests/automotive/mobly_tests/dialer/Android.bp
@@ -93,3 +93,29 @@
},
},
}
+
+python_test_host {
+ name: "BTAddressTest",
+ main: "dialer_test_import_address_details.py",
+ srcs: ["dialer_test_import_address_details.py"],
+ libs: [
+ "mobly",
+ "mbs_utils"
+ ],
+ test_suites: [
+ "catbox",
+ ],
+ test_options: {
+ unit_test: false,
+ },
+ data: [
+ // Package the snippet with the mobly test
+ ":AutomotiveSnippet",
+ ":PhoneSnippet",
+ ],
+ version: {
+ py3: {
+ embedded_launcher: true,
+ },
+ },
+}
\ No newline at end of file
diff --git a/tests/automotive/mobly_tests/dialer/dialer_test_import_address_details.py b/tests/automotive/mobly_tests/dialer/dialer_test_import_address_details.py
new file mode 100644
index 0000000..ecf3af0
--- /dev/null
+++ b/tests/automotive/mobly_tests/dialer/dialer_test_import_address_details.py
@@ -0,0 +1,125 @@
+"""
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+
+ Test Steps:
+1. Go to Dialer >Contacts and click on '>' icon in front of contact name to see the contact details
+2. Verify address information stored in phone contacts rendered in dialer app successfully
+
+"""
+
+import sys
+import logging
+import pprint
+
+from mobly import asserts
+from mobly import base_test
+from mobly import test_runner
+from mobly.controllers import android_device
+
+from mbs_utils import constants
+from mbs_utils import spectatio_utils
+from mbs_utils import bt_utils
+
+
+class ImportAddressDetailsTest(base_test.BaseTestClass):
+
+ VCF_ADDRESS_HEADER = "ADR"
+
+ def setup_class(self):
+ # Registering android_device controller module, and declaring that the test
+ # requires at least two Android devices.
+ self.ads = self.register_controller(android_device, min_number=2)
+ # # The device used to discover Bluetooth devices.
+ self.discoverer = android_device.get_device(
+ self.ads, label='auto')
+ # # Sets the tag that represents this device in logs.
+ self.discoverer.debug_tag = 'discoverer'
+ # # The device that is expected to be discovered
+ self.target = android_device.get_device(self.ads, label='phone')
+ self.target.debug_tag = 'target'
+ #
+ self.target.load_snippet('mbs', android_device.MBS_PACKAGE)
+ self.discoverer.load_snippet('mbs', android_device.MBS_PACKAGE)
+ #
+ self.call_utils = (spectatio_utils.CallUtils(self.discoverer))
+ #
+ self.bt_utils = (bt_utils.BTUtils(self.discoverer, self.target))
+
+ def get_first_address(self, vcf_path):
+ """ Reads the first address from the given vcf file'"""
+
+ with open(vcf_path, mode='r') as vcf_file:
+ for line in vcf_file:
+ if line.startswith(self.VCF_ADDRESS_HEADER):
+ return line
+
+
+
+ def setup_test(self):
+ # Upload contacts to phone device
+ file_path = constants.PATH_TO_CONTACTS_VCF_FILE
+ self.call_utils.upload_vcf_contacts_to_device(self.target, file_path)
+
+ # Pair the devices
+ self.bt_utils.pair_primary_to_secondary()
+
+ def test_import_address_details(self):
+ # Open the dialer app, and then the contacts page
+ self.call_utils.open_phone_app()
+ self.call_utils.wait_with_log(constants.WAIT_TWO_SECONDS)
+ self.call_utils.open_contacts()
+ self.call_utils.wait_with_log(constants.WAIT_TWO_SECONDS)
+ self.call_utils.open_first_contact_details()
+ self.call_utils.wait_with_log(constants.WAIT_TWO_SECONDS)
+
+ # Import the first contact's address from the discoverer device.
+ display_address = self.call_utils.get_home_address_from_details()
+
+ # Import the list of contact addresses from the VCF file.
+ vcf_line = self.get_first_address(constants.PATH_TO_CONTACTS_VCF_FILE)
+
+ # Confirm that these two lists contain the same data.
+ asserts.assert_true(
+ self.compare_display_address_to_vcf_line(display_address, vcf_line),
+ ("Displayed address does not match address stored in VCF file: " +
+ "\n\tDisplayed address: %s" +
+ "\n\tVCF address: %s") % (display_address, vcf_line))
+
+
+ def teardown_test(self):
+ # Turn Bluetooth off on both devices after test finishes.
+ self.target.mbs.btDisable()
+ self.discoverer.mbs.btDisable()
+
+ def compare_display_address_to_vcf_line(self, display_address, vcf_address):
+ """Confirm that each portion of a display-able street address appears in the vcf line.
+ Comparison is done portion-by-portion because the VCF line contains metadata and delimiters,
+ meaning this comparison could hypothetically give a false positive if parts of the address are entirely composed
+ of other parts of the address (for example, a house number being identical to the zip code."""
+ parts = display_address.split()
+ for part in parts:
+ if not part in vcf_address:
+ logging.info("\tAddress mismatch: %s not found in %s" % (part, vcf_address))
+ return False
+ return True
+
+
+
+
+if __name__ == '__main__':
+ # Take test args
+ test_runner.main()
\ No newline at end of file
diff --git a/tests/automotive/mobly_tests/dialer/dialer_test_sort_contacts_by_last_name.py b/tests/automotive/mobly_tests/dialer/dialer_test_sort_contacts_by_last_name.py
index 7c1988c..2a7da8c 100644
--- a/tests/automotive/mobly_tests/dialer/dialer_test_sort_contacts_by_last_name.py
+++ b/tests/automotive/mobly_tests/dialer/dialer_test_sort_contacts_by_last_name.py
@@ -108,15 +108,10 @@
"When sorting by last name, expected %s, found %s" % (top_contact_by_last_name,
first_contact))
-
-
-
-
-
-def teardown_test(self):
- # Turn Bluetooth off on both devices after test finishes.
- self.target.mbs.btDisable()
- self.discoverer.mbs.btDisable()
+ def teardown_test(self):
+ # Turn Bluetooth off on both devices after test finishes.
+ self.target.mbs.btDisable()
+ self.discoverer.mbs.btDisable()
diff --git a/tests/automotive/mobly_tests/mbs_utils/bt_utils.py b/tests/automotive/mobly_tests/mbs_utils/bt_utils.py
index 88b8d90..38e60a5 100644
--- a/tests/automotive/mobly_tests/mbs_utils/bt_utils.py
+++ b/tests/automotive/mobly_tests/mbs_utils/bt_utils.py
@@ -22,7 +22,7 @@
# Number of seconds for the target to stay discoverable on Bluetooth.
DISCOVERABLE_TIME = 60
-TIME_FOR_PROMPT_TO_LOAD = 3
+TIME_FOR_PROMPT_TO_LOAD = 2
class BTUtils:
"""A utility that provides access to Bluetooth connectivity controls."""
@@ -74,10 +74,9 @@
logging.info('Device \'%s\' found. Pairing.' % target_name)
self.discoverer.mbs.btPairDevice(discovered_addrs[i])
self.target_adrr = discovered_addrs[i]
- logging.info('Allowing contact sharing on secondary device.')
- time.sleep(constants.DEFAULT_WAIT_TIME_FIVE_SECS)
- self.press_allow_on_device() ## Attempts multiple presses
+ logging.info('Allowing time for contacts to sync.')
time.sleep(constants.SYNC_WAIT_TIME)
+ self.press_allow_on_device() ## Attempts multiple presses
return
def press_allow_on_device(self):
diff --git a/tests/automotive/mobly_tests/mbs_utils/contacts_test.vcf b/tests/automotive/mobly_tests/mbs_utils/contacts_test.vcf
index 88b813d..09ae844 100644
--- a/tests/automotive/mobly_tests/mbs_utils/contacts_test.vcf
+++ b/tests/automotive/mobly_tests/mbs_utils/contacts_test.vcf
@@ -1,9 +1,10 @@
BEGIN:VCARD
VERSION:2.1
-N:Goo;Anna;;;
+N:Boo;Anna;;;
FN:Anna Goo
TEL;CELL:1-844-825-5234
TEL;WORK:
+ADR;TYPE#WORK;PREF#1;LABEL#"Normality\nTesttown\, XX 00000\nTestland":;;111 Test Street;Testtown;XX;00000;Testland
END:VCARD
BEGIN:VCARD
VERSION:2.1
@@ -11,6 +12,7 @@
FN:Boris Johnson
TEL;CELL:56355
TEL;WORK:
+ADR;TYPE#WORK;PREF#1;LABEL#"Normality\nTesttown\, XX 00000\nTestland":;;111 Test Street;Testtown;XX;00000;Testland
END:VCARD
BEGIN:VCARD
VERSION:2.1
@@ -18,13 +20,15 @@
FN:John Smith Jr
TEL;CELL:611
TEL;WORK:123
+ADR;TYPE#WORK;PREF#1;LABEL#"Normality\nTesttown\, XX 00000\nTestland":;;111 Test Street;Testtown;XX;00000;Testland
END:VCARD
BEGIN:VCARD
VERSION:2.1
N:Alder;Maha;;;
-FN:Maha Alder
+FN:Maha Halder
TEL;CELL:611
TEL;WORK:1-844-825-5234
+ADR;TYPE#WORK;PREF#1;LABEL#"Normality\nTesttown\, XX 00000\nTestland":;;111 Test Street;Testtown;XX;00000;Testland
END:VCARD
BEGIN:VCARD
VERSION:2.1
@@ -32,4 +36,5 @@
FN:Sarah Williams
TEL;CELL:852
TEL;WORK:
+ADR;TYPE#WORK;PREF#1;LABEL#"Normality\nTesttown\, XX 00000\nTestland":;;111 Test Street;Testtown;XX;00000;Testland
END:VCARD
diff --git a/tests/automotive/mobly_tests/mbs_utils/spectatio_utils.py b/tests/automotive/mobly_tests/mbs_utils/spectatio_utils.py
index 2884c9d..27a4b9b 100644
--- a/tests/automotive/mobly_tests/mbs_utils/spectatio_utils.py
+++ b/tests/automotive/mobly_tests/mbs_utils/spectatio_utils.py
@@ -62,6 +62,10 @@
""" Get dialing phone number"""
return self.device.mbs.getDialedNumber()
+ def get_home_address_from_details(self):
+ """Return the home address of the contact whose details are currently being displayed"""
+ return self.device.mbs.getHomeAddress()
+
def import_contacts_from_vcf_file(self, device_target):
""" Importing contacts from VCF file"""
@@ -89,6 +93,12 @@
logging.info('Opening phone app')
self.device.mbs.openPhoneApp()
+ def open_first_contact_details(self):
+ """Open the contact details page for the first contact visible in the contact list.
+ Assumes we are on the contacts page. """
+ logging.info('Getting details for first contact on the page')
+ self.device.mbs.openFirstContactDetails()
+
def press_enter_on_device(self, device_target):
"""Press ENTER on device"""
logging.info('Press ENTER on device')
diff --git a/tests/automotive/snippets/phone/src/com/google/android/mobly/snippet/bundled/PhoneSnippet.java b/tests/automotive/snippets/phone/src/com/google/android/mobly/snippet/bundled/PhoneSnippet.java
index 1f66735..c881801 100644
--- a/tests/automotive/snippets/phone/src/com/google/android/mobly/snippet/bundled/PhoneSnippet.java
+++ b/tests/automotive/snippets/phone/src/com/google/android/mobly/snippet/bundled/PhoneSnippet.java
@@ -97,6 +97,11 @@
return mDialerHelper.get().getDialInNumber();
}
+ @Rpc(description = "Get the home address from an open contacts page.")
+ public String getHomeAddress() {
+ return mDialerHelper.get().getHomeAddress();
+ }
+
@Rpc(description = "Get the contact name for dialed number when the call is in progress.")
public String getDialedContactName() {
return mDialerHelper.get().getDialedContactName();
@@ -209,6 +214,11 @@
mDialerHelper.get().openDetailsPage(contact);
}
+ @Rpc(description = "Open details page for the first contact.")
+ public void openFirstContactDetails() {
+ mDialerHelper.get().openFirstContactDetails();
+ }
+
@Rpc(description = "Open Contacts List.")
public void openContacts() {
mDialerHelper.get().openContacts();