Use UI Automator to check if a device is commissioned on GHA instead of global var

PiperOrigin-RevId: 641204508
diff --git a/ui_automator/commission_reg_test.py b/ui_automator/commission_reg_test.py
index c210401..7e534db 100644
--- a/ui_automator/commission_reg_test.py
+++ b/ui_automator/commission_reg_test.py
@@ -6,9 +6,6 @@
 if TYPE_CHECKING:
   from ui_automator import ui_automator
 
-# TODO(b/318771536): Check if a device is commissioned on GHA.
-_commissioned: bool = False
-
 
 class CommissionRegTest(unittest.TestCase):
   """Test class for running commission regression test."""
@@ -28,16 +25,12 @@
     self.gha_room = gha_room
 
   def test_commission(self) -> None:
-    global _commissioned
-    _commissioned = False
     self.ui_automator.commission_device(
         self.device_name, self.pairing_code, self.gha_room
     )
-    # TODO(b/318771536): Check if a device is commissioned on GHA.
-    _commissioned = True
 
   def test_decommission(self) -> None:
-    if not _commissioned:
+    if not self.ui_automator.is_device_exist(self.device_name):
       self.skipTest('Device was not commissioned.')
 
     self.ui_automator.decommission_device(self.device_name)
diff --git a/ui_automator/ui_automator.py b/ui_automator/ui_automator.py
index 11e6924..154e3a1 100644
--- a/ui_automator/ui_automator.py
+++ b/ui_automator/ui_automator.py
@@ -352,6 +352,28 @@
           f' on device({self._connected_device.device_info["serial"]}).'
       ) from e
 
+  @get_android_device_ready
+  def is_device_exist(self, device_name: str) -> bool:
+    """Checks if the device exists on Google Home App.
+
+    Args:
+        device_name: Display name of commissioned device on GHA.
+
+    Raises:
+        MoblySnippetError: When running `isDeviceExist` method in snippet apk
+        encountered an error.
+
+    Returns:
+        True if the device exists on GHA.
+    """
+    try:
+      return self._connected_device.mbs.isDeviceExist(device_name)
+    except Exception as e:
+      raise errors.MoblySnippetError(
+          f'Unable to check if {device_name} exists on GHA'
+          f' on device({self._connected_device.device_info["serial"]}).'
+      ) from e
+
   def run_regression_tests(
       self,
       repeat: int | None,
diff --git a/ui_automator/ui_automator_test.py b/ui_automator/ui_automator_test.py
index 4a1f9ff..378577c 100644
--- a/ui_automator/ui_automator_test.py
+++ b/ui_automator/ui_automator_test.py
@@ -697,8 +697,12 @@
   @mock.patch.object(
       ui_automator.UIAutomator, 'decommission_device', autospec=True
   )
+  @mock.patch.object(
+      ui_automator.UIAutomator, 'is_device_exist', autospec=True
+  )
   def test_run_regression_tests_executes_for_given_number_of_times_with_failure(
       self,
+      mock_is_device_exist,
       mock_decommission_device,
       mock_commission_device,
       mock_get_all_instances,
@@ -713,6 +717,7 @@
         None,
         None,
     ]
+    mock_is_device_exist.side_effect = [True, True, False, True, True]
     mock_get_all_instances.return_value = [self.mock_android_device]
 
     with self.assertLogs() as cm:
@@ -725,6 +730,7 @@
       )
 
     self.assertEqual(mock_commission_device.call_count, 5)
+    self.assertEqual(mock_is_device_exist.call_count, 5)
     self.assertEqual(mock_decommission_device.call_count, 4)
     self.assertEqual(
         cm.output[0], 'INFO:root:Start running regression tests 5 times.'
@@ -752,8 +758,12 @@
   @mock.patch.object(
       ui_automator.UIAutomator, 'decommission_device', autospec=True
   )
+  @mock.patch.object(
+      ui_automator.UIAutomator, 'is_device_exist', autospec=True
+  )
   def test_run_regression_tests_runs_continuously_until_keyboard_interrupts(
       self,
+      mock_is_device_exist,
       mock_decommission_device,
       mock_commission_device,
       mock_get_all_instances,
@@ -769,7 +779,9 @@
         None,
         KeyboardInterrupt(),
     ]
+    mock_is_device_exist.side_effect = [True, False, True, False, True]
     mock_get_all_instances.return_value = [self.mock_android_device]
+
     with self.assertLogs() as cm:
       self.ui_automator.run_regression_tests(
           None,
@@ -781,6 +793,7 @@
 
     self.assertEqual(mock_commission_device.call_count, 6)
     self.assertEqual(mock_decommission_device.call_count, 3)
+    self.assertEqual(mock_is_device_exist.call_count, 5)
     self.assertEqual(
         cm.output[0], 'INFO:root:Start running regression tests continuously.'
     )
@@ -800,8 +813,12 @@
   @mock.patch.object(
       ui_automator.UIAutomator, 'decommission_device', autospec=True
   )
+  @mock.patch.object(
+      ui_automator.UIAutomator, 'is_device_exist', autospec=True
+  )
   def test_run_calls_run_regression_tests_and_produces_summary_in_txt(
       self,
+      mock_is_device_exist,
       mock_decommission_device,
       mock_commission_device,
       mock_get_all_instances,
@@ -822,6 +839,7 @@
         None,
         fake_error,
     ]
+    mock_is_device_exist.side_effect = [False, True, True]
     mock_get_all_instances.return_value = [self.mock_android_device]
     mock_open.side_effect = [io.StringIO(), txt_stream]
     # mock_time called by startTestRun, startTest, stopTest, and stopTestRun.
@@ -855,6 +873,7 @@
           ui_automator.run()
 
     self.assertEqual(mock_commission_device.call_count, 3)
+    self.assertEqual(mock_is_device_exist.call_count, 3)
     self.assertEqual(mock_decommission_device.call_count, 2)
     self.assertEqual(
         expected_summary + '\n\n' + expected_test_case_result,
@@ -876,8 +895,12 @@
   @mock.patch.object(
       ui_automator.UIAutomator, 'decommission_device', autospec=True
   )
+  @mock.patch.object(
+      ui_automator.UIAutomator, 'is_device_exist', autospec=True
+  )
   def test_run_calls_run_regression_tests_and_produces_summary_in_xml(
       self,
+      mock_is_device_exist,
       mock_decommission_device,
       mock_commission_device,
       mock_get_all_instances,
@@ -894,6 +917,7 @@
         None,
         None,
     ]
+    mock_is_device_exist.side_effect = [False, True, True]
     mock_decommission_device.side_effect = [
         None,
         fake_error,
@@ -986,6 +1010,7 @@
         ui_automator.run()
 
     self.assertEqual(mock_commission_device.call_count, 3)
+    self.assertEqual(mock_is_device_exist.call_count, 3)
     self.assertEqual(mock_decommission_device.call_count, 2)
     (testcases,) = re.search(
         expected_test_suite_re, xml_stream.getvalue()
@@ -1163,5 +1188,46 @@
     mock_load_snippet.assert_called_once()
     self.assertDictEqual(report_info, {})
 
+  @mock.patch.object(android_device, 'get_all_instances', autospec=True)
+  def test_is_device_exist_returns_true_when_device_exists(
+      self, mock_get_all_instances
+  ):
+    mock_get_all_instances.return_value = [self.mock_android_device]
+    self.mock_android_device.mbs.isDeviceExist.return_value = True
+
+    self.assertTrue(
+        self.ui_automator.is_device_exist(_FAKE_MATTER_DEVICE_NAME)
+    )
+
+  @mock.patch.object(android_device, 'get_all_instances', autospec=True)
+  def test_is_device_exist_returns_false_when_device_does_not_exist(
+      self, mock_get_all_instances
+  ):
+    mock_get_all_instances.return_value = [self.mock_android_device]
+    self.mock_android_device.mbs.isDeviceExist.return_value = False
+
+    self.assertFalse(
+        self.ui_automator.is_device_exist(_FAKE_MATTER_DEVICE_NAME)
+    )
+
+  @mock.patch.object(android_device, 'get_all_instances', autospec=True)
+  def test_is_device_exist_throws_an_error_when_snippet_method_throws_an_error(
+      self, mock_get_all_instances
+  ):
+    mock_get_all_instances.return_value = [self.mock_android_device]
+    self.mock_android_device.mbs.isDeviceExist.side_effect = Exception(
+        'fake-error'
+    )
+
+    with self.assertRaises(errors.MoblySnippetError) as exc:
+      self.ui_automator.is_device_exist(_FAKE_MATTER_DEVICE_NAME)
+
+    expected_error_message = (
+        f'Unable to check if {_FAKE_MATTER_DEVICE_NAME} exists on GHA'
+        f' on device({self.mock_android_device.device_info["serial"]}).'
+    )
+    self.assertEqual(expected_error_message, str(exc.exception))
+
+
 if __name__ == '__main__':
   unittest.main()