Finalize implementation of Remote Connection Service (2/4)
Change-Id: I6525ff7d7e5fbb06a45d4811ebbc319a4b32fd6b
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index de59c06..4d73918 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -33,6 +33,12 @@
<uses-permission android:name="android.permission.STOP_APP_SWITCHES" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WRITE_CALL_LOG" />
+ <!-- Protects the ability to register any PhoneAccount with a capability flags of either
+ PhoneAccount#CAPABILITY_CALL_PROVIDER or PhoneAccount#CAPABILITY_SIM_SUBSCRIPTION. -->
+ <permission
+ android:name="com.android.telecomm.permission.REGISTER_PROVIDER_OR_SUBSCRIPTION"
+ android:label="Register CALL_PROVIDER or SIM_SUBSCRIPTION PhoneAccount"
+ android:protectionLevel="signature"/>
<!-- Declare which SDK level this application was built against. This is needed so that IDEs
can check for incompatible APIs. -->
diff --git a/src/com/android/telecomm/ConnectionServiceWrapper.java b/src/com/android/telecomm/ConnectionServiceWrapper.java
index c791932..82381bd 100644
--- a/src/com/android/telecomm/ConnectionServiceWrapper.java
+++ b/src/com/android/telecomm/ConnectionServiceWrapper.java
@@ -860,6 +860,7 @@
// Only give remote connection services to this connection service if it is listed as
// the connection manager.
PhoneAccountHandle simCallManager = registrar.getSimCallManager();
+ Log.d(this, "queryRemoteConnectionServices finds simCallManager = %s", simCallManager);
if (simCallManager == null ||
!simCallManager.getComponentName().equals(getComponentName())) {
noRemoteServices(callback);
diff --git a/src/com/android/telecomm/CreateConnectionProcessor.java b/src/com/android/telecomm/CreateConnectionProcessor.java
index f3449ff..5a186f4 100644
--- a/src/com/android/telecomm/CreateConnectionProcessor.java
+++ b/src/com/android/telecomm/CreateConnectionProcessor.java
@@ -147,6 +147,8 @@
}
PhoneAccountHandle simCallManager =
TelecommApp.getInstance().getPhoneAccountRegistrar().getSimCallManager();
+
+ Log.d(this, "adjustAttemptsForWifi finds simCallManager = %s", simCallManager);
if (simCallManager != null &&
!Objects.equals(simCallManager, mAttemptRecords.get(0).targetPhoneAccount)) {
mAttemptRecords.set(
diff --git a/src/com/android/telecomm/TelecommServiceImpl.java b/src/com/android/telecomm/TelecommServiceImpl.java
index 3598422..9366f84 100644
--- a/src/com/android/telecomm/TelecommServiceImpl.java
+++ b/src/com/android/telecomm/TelecommServiceImpl.java
@@ -44,7 +44,8 @@
* Implementation of the ITelecomm interface.
*/
public class TelecommServiceImpl extends ITelecommService.Stub {
- private static final String TELEPHONY_PACKAGE_NAME = "com.android.phone";
+ private static final String REGISTER_PROVIDER_OR_SUBSCRIPTION =
+ "com.android.telecomm.permission.REGISTER_PROVIDER_OR_SUBSCRIPTION";
/** ${inheritDoc} */
@Override
@@ -195,7 +196,7 @@
account.getAccountHandle().getComponentName().getPackageName());
if (PhoneAccountRegistrar.has(account, PhoneAccount.CAPABILITY_CALL_PROVIDER) ||
PhoneAccountRegistrar.has(account, PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
- enforceModifyPermissionOrCallingPackage(TELEPHONY_PACKAGE_NAME);
+ enforceRegisterProviderOrSubscriptionPermission();
}
mPhoneAccountRegistrar.registerPhoneAccount(account);
} catch (Exception e) {
@@ -410,6 +411,11 @@
}
}
+ private void enforceRegisterProviderOrSubscriptionPermission() {
+ TelecommApp.getInstance().enforceCallingOrSelfPermission(
+ REGISTER_PROVIDER_OR_SUBSCRIPTION, null);
+ }
+
private void enforceModifyPermissionOrCallingPackage(String packageName) {
// TODO(santoscordon): Use a new telecomm permission for this instead of reusing modify.
try {
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index fecfffb..bbc3292 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -15,10 +15,13 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.telecomm.tests">
+ coreApp="true"
+ package="com.android.telecomm.tests">
<!-- Test connection service outgoing video preview. -->
<uses-permission android:name="android.permission.CAMERA" />
+ <uses-permission
+ android:name="com.android.telecomm.permission.REGISTER_PROVIDER_OR_SUBSCRIPTION" />
<application android:label="@string/app_name">
<uses-library android:name="android.test.runner" />
@@ -31,6 +34,12 @@
</intent-filter>
</service>
+ <service android:name="com.android.telecomm.testapps.TestConnectionManager">
+ <intent-filter>
+ <action android:name="android.telecomm.ConnectionService" />
+ </intent-filter>
+ </service>
+
<activity android:name="com.android.telecomm.testapps.TestCallActivity"
android:label="@string/testCallActivityLabel">
<intent-filter>
diff --git a/tests/res/drawable-xhdpi/stat_sys_phone_call.png b/tests/res/drawable-xhdpi/stat_sys_phone_call.png
new file mode 100644
index 0000000..1bb4340
--- /dev/null
+++ b/tests/res/drawable-xhdpi/stat_sys_phone_call.png
Binary files differ
diff --git a/tests/src/com/android/telecomm/testapps/CallServiceNotifier.java b/tests/src/com/android/telecomm/testapps/CallServiceNotifier.java
index 0dbb0b1..debfc9b 100644
--- a/tests/src/com/android/telecomm/testapps/CallServiceNotifier.java
+++ b/tests/src/com/android/telecomm/testapps/CallServiceNotifier.java
@@ -16,6 +16,8 @@
package com.android.telecomm.testapps;
+import com.android.telecomm.tests.R;
+
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -88,19 +90,28 @@
* Registers a phone account with telecomm.
*/
public void registerPhoneAccount(Context context) {
- PhoneAccount account = new PhoneAccount(
+ TelecommManager telecommManager =
+ (TelecommManager) context.getSystemService(Context.TELECOMM_SERVICE);
+ telecommManager.registerPhoneAccount(new PhoneAccount(
new PhoneAccountHandle(
new ComponentName(context, TestConnectionService.class),
PHONE_ACCOUNT_ID),
Uri.parse("tel:555-TEST"),
"555-TEST",
PhoneAccount.CAPABILITY_CALL_PROVIDER,
- 0, // iconResId
+ R.drawable.stat_sys_phone_call,
"Dummy Service",
- "a short description for the dummy service");
- TelecommManager telecommManager =
- (TelecommManager) context.getSystemService(Context.TELECOMM_SERVICE);
- telecommManager.registerPhoneAccount(account);
+ "a short description for the dummy service"));
+ telecommManager.registerPhoneAccount(new PhoneAccount(
+ new PhoneAccountHandle(
+ new ComponentName(context, TestConnectionManager.class),
+ PHONE_ACCOUNT_ID),
+ Uri.parse("tel:555-CMGR"),
+ "555-CMGR",
+ PhoneAccount.CAPABILITY_CONNECTION_MANAGER,
+ R.drawable.stat_sys_phone_call,
+ "Dummy Connection Manager",
+ "a short description for the dummy connection manager"));
}
/**
diff --git a/tests/src/com/android/telecomm/testapps/TestConnectionManager.java b/tests/src/com/android/telecomm/testapps/TestConnectionManager.java
new file mode 100644
index 0000000..6a8433a
--- /dev/null
+++ b/tests/src/com/android/telecomm/testapps/TestConnectionManager.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2013 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.telecomm.testapps;
+
+import android.app.PendingIntent;
+import android.net.Uri;
+import android.telecomm.CallAudioState;
+import android.telecomm.Connection;
+import android.telecomm.ConnectionRequest;
+import android.telecomm.ConnectionService;
+import android.telecomm.PhoneAccountHandle;
+import android.telecomm.RemoteConnection;
+import android.telecomm.StatusHints;
+import android.util.Log;
+
+import java.util.Random;
+
+/**
+ * Service which acts as a fake ConnectionManager if so configured.
+ * TODO(santoscordon): Rename all classes in the directory to Dummy* (e.g., DummyConnectionService).
+ */
+public class TestConnectionManager extends ConnectionService {
+ /**
+ * Random number generator used to generate phone numbers.
+ */
+ private Random mRandom = new Random();
+
+ private final class TestManagedConnection extends Connection {
+ private final RemoteConnection.Listener mProxyListener = new RemoteConnection.Listener() {
+ @Override
+ public void onStateChanged(RemoteConnection connection, int state) {
+ setState(state);
+ }
+
+ @Override
+ public void onDisconnected(RemoteConnection connection, int cause, String message) {
+ setDisconnected(cause, message);
+ destroy();
+ }
+
+ @Override
+ public void onRequestingRingback(RemoteConnection connection, boolean ringback) {
+ setRequestingRingback(ringback);
+ }
+
+ @Override
+ public void onCallCapabilitiesChanged(RemoteConnection connection,
+ int callCapabilities) {
+ setCallCapabilities(callCapabilities);
+ }
+
+ @Override
+ public void onPostDialWait(RemoteConnection connection, String remainingDigits) {
+ setPostDialWait(remainingDigits);
+ }
+
+ @Override
+ public void onAudioModeIsVoipChanged(RemoteConnection connection, boolean isVoip) {
+ setAudioModeIsVoip(isVoip);
+ }
+
+ @Override
+ public void onStatusHintsChanged(RemoteConnection connection, StatusHints statusHints) {
+ setStatusHints(statusHints);
+ }
+
+ @Override
+ public void onVideoStateChanged(RemoteConnection connection, int videoState) {
+ setVideoState(videoState);
+ }
+
+ @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 onStartActivityFromInCall(
+ RemoteConnection connection, PendingIntent intent) {
+ startActivityFromInCall(intent);
+ }
+
+ @Override
+ public void onDestroyed(RemoteConnection connection) {
+ destroy();
+ }
+ };
+
+ private final RemoteConnection mRemoteConnection;
+ private final boolean mIsIncoming;
+
+ TestManagedConnection(RemoteConnection remoteConnection, boolean isIncoming) {
+ mRemoteConnection = remoteConnection;
+ mIsIncoming = isIncoming;
+ mRemoteConnection.addListener(mProxyListener);
+ setState(mRemoteConnection.getState());
+ }
+
+ @Override
+ public void onAbort() {
+ mRemoteConnection.abort();
+ }
+
+ /** ${inheritDoc} */
+ @Override
+ public void onAnswer(int videoState) {
+ mRemoteConnection.answer(videoState);
+ }
+
+ /** ${inheritDoc} */
+ @Override
+ public void onDisconnect() {
+ mRemoteConnection.disconnect();
+ }
+
+ /** ${inheritDoc} */
+ @Override
+ public void onHold() {
+ mRemoteConnection.hold();
+ }
+
+ /** ${inheritDoc} */
+ @Override
+ public void onReject() {
+ mRemoteConnection.reject();
+ }
+
+ /** ${inheritDoc} */
+ @Override
+ public void onUnhold() {
+ mRemoteConnection.unhold();
+ }
+
+ @Override
+ public void onSetAudioState(CallAudioState state) {
+ mRemoteConnection.setAudioState(state);
+ }
+
+ private void setState(int state) {
+ log("setState: " + state);
+ switch (state) {
+ case State.ACTIVE:
+ setActive();
+ break;
+ case State.HOLDING:
+ setOnHold();
+ break;
+ case State.DIALING:
+ setDialing();
+ break;
+ case State.RINGING:
+ setRinging();
+ break;
+ }
+ }
+ }
+
+ private static void log(String msg) {
+ Log.w("telecomtestcs", "[TestConnectionService] " + msg);
+ }
+
+ @Override
+ public Connection onCreateOutgoingConnection(
+ PhoneAccountHandle connectionManagerAccount,
+ final ConnectionRequest request) {
+ return new TestManagedConnection(
+ createRemoteOutgoingConnection(
+ request.getAccountHandle(),
+ request),
+ false);
+ }
+
+ @Override
+ public Connection onCreateIncomingConnection(
+ PhoneAccountHandle connectionManagerAccount,
+ final ConnectionRequest request) {
+ return new TestManagedConnection(
+ createRemoteOutgoingConnection(
+ request.getAccountHandle(),
+ request),
+ true);
+ }
+}