Add more CTS tests around Telecomm flows
Add additional Telecomm CTS tests which verify both failed calls as
well as basic RemoteConnection behavior.
Bug: 16431051
Bug: 16844815
Change-Id: I16e4699347bf128cfd8ea27feae751d0121399db
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 5f6dd0d..17071e3 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -1159,7 +1159,41 @@
<meta-data android:name="test_required_features" android:value="android.hardware.telephony"/>
</activity>
- <service android:name=".telecomm.CancelCallTestActivity$CancellingConnectionService"
+ <service android:name=".telecomm.CancelCallTestActivity$ConnectionService"
+ android:permission="android.permission.BIND_CONNECTION_SERVICE">
+ <intent-filter>
+ <action android:name="android.telecomm.ConnectionService" />
+ </intent-filter>
+ </service>
+
+ <activity android:name=".telecomm.FailedCallTestActivity"
+ android:label="@string/telecomm_failed_call_title">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.cts.intent.category.MANUAL_TEST" />
+ </intent-filter>
+ <meta-data android:name="test_category" android:value="@string/test_category_telecomm" />
+ <meta-data android:name="test_parent" android:value="com.android.cts.verifier.telecomm.TelecommTestActivity" />
+ </activity>
+
+ <service android:name=".telecomm.FailedCallTestActivity$ConnectionService"
+ android:permission="android.permission.BIND_CONNECTION_SERVICE">
+ <intent-filter>
+ <action android:name="android.telecomm.ConnectionService" />
+ </intent-filter>
+ </service>
+
+ <activity android:name=".telecomm.BasicCallTestActivity"
+ android:label="@string/telecomm_basic_call_title">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.cts.intent.category.MANUAL_TEST" />
+ </intent-filter>
+ <meta-data android:name="test_category" android:value="@string/test_category_telecomm" />
+ <meta-data android:name="test_parent" android:value="com.android.cts.verifier.telecomm.TelecommTestActivity" />
+ </activity>
+
+ <service android:name=".telecomm.BasicCallTestActivity$ConnectionService"
android:permission="android.permission.BIND_CONNECTION_SERVICE">
<intent-filter>
<action android:name="android.telecomm.ConnectionService" />
diff --git a/apps/CtsVerifier/res/layout/telecomm_test_activity.xml b/apps/CtsVerifier/res/layout/telecomm_test_activity.xml
index e5cebe1..c885f8a 100644
--- a/apps/CtsVerifier/res/layout/telecomm_test_activity.xml
+++ b/apps/CtsVerifier/res/layout/telecomm_test_activity.xml
@@ -22,6 +22,11 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/telecomm_open_settings" />
+ <EditText android:id="@+id/phone_number"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/telecomm_default_phone_number"
+ android:hint="@string/telecomm_phone_number_hint" />
<Button android:id="@+id/simulate_call"
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 4882946..b4097a3 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -1128,10 +1128,22 @@
</string>
<string name="telecomm_open_settings">Open settings</string>
<string name="telecomm_simulate_call">Place call</string>
+ <string name="telecomm_default_phone_number">555-263-7643</string>
+ <string name="telecomm_phone_number_hint">Phone number to call</string>
<string name="telecomm_cancel_call_title">Canceled Call Test</string>
<string name="telecomm_cancel_call_info">This tests to make sure that canceled calls are handled correctly.
Press the \"Open settings\" button and make sure that \"Call Cancel Manager\" is the default Wi-Fi calling account.
Then press the \"Place call\" button; the test will pass (or fail) automatically.
</string>
+ <string name="telecomm_failed_call_title">Failed Call Test</string>
+ <string name="telecomm_failed_call_info">This tests to make sure that failed calls are handled correctly.
+ Press the \"Open settings\" button and make sure that \"Call Failed Manager\" is the default Wi-Fi calling account.
+ Then press the \"Place call\" button; the test will pass (or fail) automatically.
+ </string>
+ <string name="telecomm_basic_call_title">Basic Call Test</string>
+ <string name="telecomm_basic_call_info">This tests to make sure that basic calls are handled correctly.
+ Press the \"Open settings\" button and make sure that \"Basic Call Manager\" is the default Wi-Fi calling account.
+ Then press the \"Place call\" button; the test will pass (or fail) automatically.
+ </string>
</resources>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/telecomm/BasicCallTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/telecomm/BasicCallTestActivity.java
new file mode 100644
index 0000000..6e5fab2
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/telecomm/BasicCallTestActivity.java
@@ -0,0 +1,151 @@
+package com.android.cts.verifier.telecomm;
+
+import com.android.cts.verifier.R;
+
+import android.net.Uri;
+import android.os.Handler;
+import android.os.SystemClock;
+import android.telecomm.Connection;
+import android.telecomm.ConnectionRequest;
+import android.telecomm.PhoneAccountHandle;
+import android.telecomm.RemoteConnection;
+import android.telecomm.StatusHints;
+import android.util.Log;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Tests that a basic call with RemoteConnections will go through. When this ConnectionService is
+ * notified of an outgoing call, it will create a Connection which wraps a RemoteConnection. Then,
+ * once the RemoteConnection starts dialing, it will disconnect the call and the test will pass.
+ */
+public class BasicCallTestActivity extends TelecommBaseTestActivity {
+ private static final Semaphore sLock = new Semaphore(0);
+
+ @Override
+ protected int getTestTitleResource() {
+ return R.string.telecomm_basic_call_title;
+ }
+
+ @Override
+ protected int getTestInfoResource() {
+ return R.string.telecomm_basic_call_info;
+ }
+
+ @Override
+ protected Class<? extends android.telecomm.ConnectionService> getConnectionService() {
+ return ConnectionService.class;
+ }
+
+ @Override
+ protected String getConnectionServiceLabel() {
+ return "Basic Call Manager";
+ }
+
+ @Override
+ protected boolean onCallPlacedBackgroundThread() {
+ try {
+ if (!sLock.tryAcquire(5000, TimeUnit.MILLISECONDS)) {
+ return false;
+ }
+
+ // Wait for the listeners to be fired so the call is cleaned up.
+ SystemClock.sleep(1000);
+
+ return !getTelecommManager().isInCall();
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ public static class ConnectionService extends android.telecomm.ConnectionService {
+ @Override
+ public Connection onCreateOutgoingConnection(
+ PhoneAccountHandle connectionManagerPhoneAccount,
+ ConnectionRequest request) {
+ RemoteConnection remoteConnection =
+ createRemoteOutgoingConnection(connectionManagerPhoneAccount, request);
+ return new ProxyConnection(remoteConnection);
+ }
+ }
+
+ private static class ProxyConnection extends Connection {
+ private final RemoteConnection mRemoteConnection;
+
+ private final RemoteConnection.Listener mListener = new RemoteConnection.Listener() {
+ @Override
+ public void onStateChanged(RemoteConnection connection, int state) {
+ switch (state) {
+ case Connection.STATE_ACTIVE:
+ setActive();
+ break;
+ case Connection.STATE_DIALING:
+ setDialing();
+ break;
+ case Connection.STATE_DISCONNECTED:
+ sLock.release();
+ break;
+ case Connection.STATE_HOLDING:
+ setOnHold();
+ break;
+ case Connection.STATE_INITIALIZING:
+ setInitializing();
+ break;
+ case Connection.STATE_NEW:
+ setInitialized();
+ break;
+ case Connection.STATE_RINGING:
+ setRinging();
+ break;
+ }
+ }
+
+ @Override
+ public void onDisconnected(RemoteConnection connection, int disconnectCauseCode,
+ String disconnectCauseMessage) {
+ setDisconnected(disconnectCauseCode, disconnectCauseMessage);
+ }
+
+ @Override
+ public void onStatusHintsChanged(RemoteConnection connection, StatusHints statusHints) {
+ setStatusHints(statusHints);
+ }
+
+ @Override
+ public void onHandleChanged(RemoteConnection connection, Uri handle, int presentation) {
+ setHandle(handle, presentation);
+ }
+
+ @Override
+ public void onCallerDisplayNameChanged(RemoteConnection connection,
+ String callerDisplayName,
+ int presentation) {
+ setCallerDisplayName(callerDisplayName, presentation);
+ }
+
+ @Override
+ public void onDestroyed(RemoteConnection connection) {
+ destroy();
+ }
+ };
+
+ public ProxyConnection(RemoteConnection connection) {
+ mRemoteConnection = connection;
+ if (connection.getState() == Connection.STATE_DISCONNECTED) {
+ sLock.release();
+ } else {
+ mRemoteConnection.addListener(mListener);
+ }
+ }
+
+ @Override
+ public void onSetState(int state) {
+ if (state == Connection.STATE_DIALING) {
+ // Good enough; let's disconnect this call.
+ mRemoteConnection.disconnect();
+ sLock.release();
+ }
+ }
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/telecomm/CancelCallTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/telecomm/CancelCallTestActivity.java
index 088cf49..d3fb0bf 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/telecomm/CancelCallTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/telecomm/CancelCallTestActivity.java
@@ -16,106 +16,62 @@
package com.android.cts.verifier.telecomm;
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
-import android.content.ComponentName;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
import android.os.SystemClock;
import android.telecomm.Connection;
import android.telecomm.ConnectionRequest;
-import android.telecomm.ConnectionService;
-import android.telecomm.PhoneAccount;
import android.telecomm.PhoneAccountHandle;
-import android.telecomm.TelecommManager;
-import android.view.View;
+
+import com.android.cts.verifier.R;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
-public class CancelCallTestActivity extends PassFailButtons.Activity {
+/**
+ * Tests that a call can be canceled by a ConnectionService (and that the cancelation is respected).
+ * Once the ConnectionService returns a canceled connection, the test verifies that Telecomm does
+ * not have any active calls. If this is the case, the test will pass.
+ */
+public class CancelCallTestActivity extends TelecommBaseTestActivity {
private static final Semaphore sLock = new Semaphore(0);
- private PhoneAccountHandle mPhoneAccountHandle;
-
@Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setResult(RESULT_CANCELED);
- setContentView(R.layout.telecomm_test_activity);
- setPassFailButtonClickListeners();
- setInfoResources(R.string.telecomm_cancel_call_title, R.string.telecomm_cancel_call_info, 0);
-
- findViewById(R.id.open_settings).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- mPhoneAccountHandle = new PhoneAccountHandle(
- new ComponentName(CancelCallTestActivity.this,
- CancellingConnectionService.class),
- getClass().getSimpleName()
- );
- PhoneAccount account = new PhoneAccount.Builder(mPhoneAccountHandle,
- "Call Cancel Manager")
- .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER)
- .build();
-
- getTelecommManager().registerPhoneAccount(account);
-
- Intent i = new Intent(Intent.ACTION_MAIN)
- .setClassName("com.android.telecomm",
- "com.android.telecomm.PhoneAccountPreferencesActivity");
- startActivity(i);
- }
- });
-
- findViewById(R.id.simulate_call).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- new Thread() {
- @Override
- public void run() {
- super.run();
-
- Intent call = new Intent(Intent.ACTION_CALL);
- call.setData(Uri.parse("tel:5552637643"));
- startActivity(call);
- try {
- if (!sLock.tryAcquire(1000, TimeUnit.MILLISECONDS)) {
- setTestResultAndFinish(false);
- return;
- }
-
- // Wait for the listeners to be fired so the call is cleaned up.
- SystemClock.sleep(1000);
-
- // Make sure that there aren't any ongoing calls.
- setTestResultAndFinish(!getTelecommManager().isInCall());
- } catch (Exception e) {
- setTestResultAndFinish(false);
- return;
- }
- }
- }.start();
- }
- });
- }
-
- private TelecommManager getTelecommManager() {
- return (TelecommManager) getSystemService(TELECOMM_SERVICE);
+ protected int getTestTitleResource() {
+ return R.string.telecomm_cancel_call_title;
}
@Override
- public void setTestResultAndFinish(boolean passed) {
- super.setTestResultAndFinish(passed);
- if (mPhoneAccountHandle != null) {
- getTelecommManager().unregisterPhoneAccount(mPhoneAccountHandle);
+ protected int getTestInfoResource() {
+ return R.string.telecomm_cancel_call_info;
+ }
+
+ @Override
+ protected Class<? extends android.telecomm.ConnectionService> getConnectionService() {
+ return ConnectionService.class;
+ }
+
+ @Override
+ protected String getConnectionServiceLabel() {
+ return "Call Cancel Manager";
+ }
+
+ @Override
+ protected boolean onCallPlacedBackgroundThread() {
+ try {
+ if (!sLock.tryAcquire(1000, TimeUnit.MILLISECONDS)) {
+ return false;
+ }
+
+ // Wait for the listeners to be fired so the call is cleaned up.
+ SystemClock.sleep(1000);
+
+ // Make sure that there aren't any ongoing calls.
+ return !getTelecommManager().isInCall();
+ } catch (Exception e) {
+ return false;
}
}
- public static class CancellingConnectionService extends ConnectionService {
+ public static class ConnectionService extends android.telecomm.ConnectionService {
@Override
public Connection onCreateOutgoingConnection(
PhoneAccountHandle connectionManagerPhoneAccount,
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/telecomm/FailedCallTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/telecomm/FailedCallTestActivity.java
new file mode 100644
index 0000000..86137f6
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/telecomm/FailedCallTestActivity.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+package com.android.cts.verifier.telecomm;
+
+import android.os.SystemClock;
+import android.telecomm.Connection;
+import android.telecomm.ConnectionRequest;
+import android.telecomm.PhoneAccountHandle;
+import android.telephony.DisconnectCause;
+
+import com.android.cts.verifier.R;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Tests that a connection manager can fail calls and they're handled appropriately. That is, when
+ * a call is failed, it will not go through. The flow here is that the ConnectionService will say
+ * that the call failed because it's busy, and then make sure that there are no active calls. If
+ * this is the case, the test will pass.
+ */
+public class FailedCallTestActivity extends TelecommBaseTestActivity {
+ private static final Semaphore sLock = new Semaphore(0);
+
+ @Override
+ protected int getTestTitleResource() {
+ return R.string.telecomm_failed_call_title;
+ }
+
+ @Override
+ protected int getTestInfoResource() {
+ return R.string.telecomm_failed_call_info;
+ }
+
+ @Override
+ protected Class<? extends android.telecomm.ConnectionService> getConnectionService() {
+ return ConnectionService.class;
+ }
+
+ @Override
+ protected String getConnectionServiceLabel() {
+ return "Call Failed Manager";
+ }
+
+ @Override
+ protected boolean onCallPlacedBackgroundThread() {
+ try {
+ if (!sLock.tryAcquire(1000, TimeUnit.MILLISECONDS)) {
+ return false;
+ }
+
+ // Wait for the listeners to be fired so the call is cleaned up.
+ SystemClock.sleep(1000);
+
+ // Make sure that there aren't any ongoing calls.
+ return !getTelecommManager().isInCall();
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ public static class ConnectionService extends android.telecomm.ConnectionService {
+ @Override
+ public Connection onCreateOutgoingConnection(
+ PhoneAccountHandle connectionManagerPhoneAccount,
+ ConnectionRequest request) {
+ sLock.release();
+ return Connection.createFailedConnection(DisconnectCause.BUSY,
+ "Test; no need to continue");
+ }
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/telecomm/TelecommBaseTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/telecomm/TelecommBaseTestActivity.java
new file mode 100644
index 0000000..512e306
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/telecomm/TelecommBaseTestActivity.java
@@ -0,0 +1,120 @@
+package com.android.cts.verifier.telecomm;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.telecomm.ConnectionService;
+import android.telecomm.PhoneAccount;
+import android.telecomm.PhoneAccountHandle;
+import android.telecomm.TelecommManager;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+
+import java.util.Objects;
+
+public abstract class TelecommBaseTestActivity extends PassFailButtons.Activity {
+ protected PhoneAccountHandle mPhoneAccountHandle;
+
+ private Button mOpenSettingsBtn;
+ private Button mPlaceCallBtn;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setResult(RESULT_CANCELED);
+ setContentView(R.layout.telecomm_test_activity);
+ setPassFailButtonClickListeners();
+ setInfoResources(getTestTitleResource(), getTestInfoResource(), 0);
+
+ mOpenSettingsBtn = (Button) findViewById(R.id.open_settings);
+ mOpenSettingsBtn.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mPhoneAccountHandle = new PhoneAccountHandle(
+ new ComponentName(getApplicationContext(), getConnectionService()),
+ getClass().getSimpleName()
+ );
+ PhoneAccount account = new PhoneAccount.Builder(mPhoneAccountHandle,
+ getConnectionServiceLabel())
+ .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER)
+ .build();
+
+ getTelecommManager().registerPhoneAccount(account);
+
+ Intent i = new Intent(TelecommManager.ACTION_CHANGE_PHONE_ACCOUNTS);
+ startActivity(i);
+ }
+ });
+
+ mPlaceCallBtn = (Button) findViewById(R.id.simulate_call);
+ mPlaceCallBtn.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ runTest();
+ }
+ });
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ PhoneAccountHandle defaultConnectionManager = getTelecommManager().getConnectionManager();
+ boolean isDefaultConnectionManager = mPhoneAccountHandle != null &&
+ Objects.equals(mPhoneAccountHandle, defaultConnectionManager);
+ mOpenSettingsBtn.setEnabled(!isDefaultConnectionManager);
+ mPlaceCallBtn.setEnabled(isDefaultConnectionManager);
+ }
+
+ abstract protected int getTestTitleResource();
+
+ abstract protected int getTestInfoResource();
+
+ abstract protected Class<? extends ConnectionService> getConnectionService();
+
+ abstract protected String getConnectionServiceLabel();
+
+ /**
+ * Perform any tests once the call has been placed. This is called from a background thread, so
+ * it is safe to block until the result is known.
+ *
+ * @return True if the test passed.
+ */
+ abstract protected boolean onCallPlacedBackgroundThread();
+
+ protected void runTest() {
+ new Thread() {
+ @Override
+ public void run() {
+ EditText phoneNumberEdit = (EditText) findViewById(R.id.phone_number);
+ String numberText = phoneNumberEdit.getText().toString();
+ Uri number = Uri.fromParts("tel", numberText, null);
+
+ Intent call = new Intent(Intent.ACTION_CALL);
+ call.setData(number);
+ startActivity(call);
+
+ boolean passed = onCallPlacedBackgroundThread();
+ setTestResultAndFinish(passed);
+ }
+ }.start();
+ }
+
+ protected TelecommManager getTelecommManager() {
+ return (TelecommManager) getSystemService(TELECOMM_SERVICE);
+ }
+
+ @Override
+ public void setTestResultAndFinish(boolean passed) {
+ super.setTestResultAndFinish(passed);
+ if (mPhoneAccountHandle != null) {
+ getTelecommManager().unregisterPhoneAccount(mPhoneAccountHandle);
+ }
+ }
+}