Publish new Telecomm API for Connection Services
Creates a new API for Connection Services providing phone connections to the Android system. Supersedes CallService API, which will be gradually replaced by this one. Change-Id: Ie4b06c1b0843a777c5b8ee9c5dd12b9d9f990980
This commit is contained in:
@@ -26599,6 +26599,83 @@ package android.telecomm {
|
||||
enum_constant public static final android.telecomm.CallState RINGING;
|
||||
}
|
||||
|
||||
public abstract class Connection {
|
||||
ctor protected Connection();
|
||||
method public final android.telecomm.CallAudioState getCallAudioState();
|
||||
method public final android.net.Uri getHandle();
|
||||
method protected void onAbort();
|
||||
method protected void onAnswer();
|
||||
method protected void onDisconnect();
|
||||
method protected void onHold();
|
||||
method protected void onPlayDtmfTone(char);
|
||||
method protected void onReject();
|
||||
method protected void onSetAudioState(android.telecomm.CallAudioState);
|
||||
method protected void onSetSignal(android.os.Bundle);
|
||||
method protected void onStopDtmfTone();
|
||||
method protected void onUnhold();
|
||||
method protected void setActive();
|
||||
method public void setAudioState(android.telecomm.CallAudioState);
|
||||
method protected void setDialing();
|
||||
method protected void setDisconnected(int, java.lang.String);
|
||||
method protected void setHandle(android.net.Uri);
|
||||
method protected void setOnHold();
|
||||
method protected void setRinging();
|
||||
method public static java.lang.String stateToString(int);
|
||||
}
|
||||
|
||||
public static abstract interface Connection.Listener {
|
||||
method public abstract void onAudioStateChanged(android.telecomm.Connection, android.telecomm.CallAudioState);
|
||||
method public abstract void onDestroyed(android.telecomm.Connection);
|
||||
method public abstract void onDisconnected(android.telecomm.Connection, int, java.lang.String);
|
||||
method public abstract void onHandleChanged(android.telecomm.Connection, android.net.Uri);
|
||||
method public abstract void onSignalChanged(android.telecomm.Connection, android.os.Bundle);
|
||||
method public abstract void onStateChanged(android.telecomm.Connection, int);
|
||||
}
|
||||
|
||||
public static class Connection.ListenerBase implements android.telecomm.Connection.Listener {
|
||||
ctor public Connection.ListenerBase();
|
||||
method public void onAudioStateChanged(android.telecomm.Connection, android.telecomm.CallAudioState);
|
||||
method public void onDestroyed(android.telecomm.Connection);
|
||||
method public void onDisconnected(android.telecomm.Connection, int, java.lang.String);
|
||||
method public void onHandleChanged(android.telecomm.Connection, android.net.Uri);
|
||||
method public void onSignalChanged(android.telecomm.Connection, android.os.Bundle);
|
||||
method public void onStateChanged(android.telecomm.Connection, int);
|
||||
}
|
||||
|
||||
public final class Connection.State {
|
||||
field public static final int ACTIVE = 3; // 0x3
|
||||
field public static final int DIALING = 2; // 0x2
|
||||
field public static final int DISCONNECTED = 5; // 0x5
|
||||
field public static final int HOLDING = 4; // 0x4
|
||||
field public static final int NEW = 0; // 0x0
|
||||
field public static final int RINGING = 1; // 0x1
|
||||
}
|
||||
|
||||
public final class ConnectionRequest {
|
||||
ctor public ConnectionRequest(android.net.Uri, android.os.Bundle);
|
||||
method public android.os.Bundle getExtras();
|
||||
method public android.net.Uri getHandle();
|
||||
}
|
||||
|
||||
public abstract class ConnectionService extends android.telecomm.CallService {
|
||||
ctor public ConnectionService();
|
||||
method public final void abort(java.lang.String);
|
||||
method public final void answer(java.lang.String);
|
||||
method public final void call(android.telecomm.CallInfo);
|
||||
method public final void disconnect(java.lang.String);
|
||||
method public final void hold(java.lang.String);
|
||||
method public final void isCompatibleWith(android.telecomm.CallInfo);
|
||||
method public final void onAudioStateChanged(java.lang.String, android.telecomm.CallAudioState);
|
||||
method public void onCreateConnections(android.telecomm.ConnectionRequest, android.telecomm.Response<android.telecomm.ConnectionRequest, android.telecomm.Connection>);
|
||||
method public void onCreateIncomingConnection(android.telecomm.ConnectionRequest, android.telecomm.Response<android.telecomm.ConnectionRequest, android.telecomm.Connection>);
|
||||
method public void onFindSubscriptions(android.net.Uri, android.telecomm.Response<android.net.Uri, android.telecomm.Subscription>);
|
||||
method public final void playDtmfTone(java.lang.String, char);
|
||||
method public final void reject(java.lang.String);
|
||||
method public final void setIncomingCallId(java.lang.String, android.os.Bundle);
|
||||
method public final void stopDtmfTone(java.lang.String);
|
||||
method public final void unhold(java.lang.String);
|
||||
}
|
||||
|
||||
public class GatewayInfo implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public android.net.Uri getGatewayHandle();
|
||||
@@ -26650,6 +26727,18 @@ package android.telecomm {
|
||||
method protected abstract void updateCall(android.telecomm.InCallCall);
|
||||
}
|
||||
|
||||
public abstract interface Response {
|
||||
method public abstract void onError(IN, java.lang.String);
|
||||
method public abstract void onResult(IN, OUT...);
|
||||
}
|
||||
|
||||
public class Subscription implements android.os.Parcelable {
|
||||
ctor public Subscription();
|
||||
method public int describeContents();
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final android.os.Parcelable.Creator CREATOR;
|
||||
}
|
||||
|
||||
public final class TelecommConstants {
|
||||
ctor public TelecommConstants();
|
||||
field public static final java.lang.String ACTION_CALL_SERVICE;
|
||||
|
||||
412
telecomm/java/android/telecomm/Connection.java
Normal file
412
telecomm/java/android/telecomm/Connection.java
Normal file
@@ -0,0 +1,412 @@
|
||||
/*
|
||||
* 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 android.telecomm;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Represents a connection to a remote endpoint that carries voice traffic.
|
||||
*/
|
||||
public abstract class Connection {
|
||||
|
||||
private static String TAG = Connection.class.getSimpleName();
|
||||
|
||||
public interface Listener {
|
||||
void onStateChanged(Connection c, int state);
|
||||
void onAudioStateChanged(Connection c, CallAudioState state);
|
||||
void onHandleChanged(Connection c, Uri newHandle);
|
||||
void onSignalChanged(Connection c, Bundle details);
|
||||
void onDisconnected(Connection c, int cause, String message);
|
||||
void onDestroyed(Connection c);
|
||||
}
|
||||
|
||||
public static class ListenerBase implements Listener {
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void onStateChanged(Connection c, int state) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void onAudioStateChanged(Connection c, CallAudioState state) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void onHandleChanged(Connection c, Uri newHandle) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void onSignalChanged(Connection c, Bundle details) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void onDisconnected(Connection c, int cause, String message) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void onDestroyed(Connection c) {}
|
||||
}
|
||||
|
||||
public final class State {
|
||||
private State() {}
|
||||
|
||||
public static final int NEW = 0;
|
||||
public static final int RINGING = 1;
|
||||
public static final int DIALING = 2;
|
||||
public static final int ACTIVE = 3;
|
||||
public static final int HOLDING = 4;
|
||||
public static final int DISCONNECTED = 5;
|
||||
}
|
||||
|
||||
private final Set<Listener> mListeners = new HashSet<>();
|
||||
private int mState = State.NEW;
|
||||
private CallAudioState mCallAudioState;
|
||||
private Uri mHandle;
|
||||
|
||||
/**
|
||||
* Create a new Connection.
|
||||
*/
|
||||
protected Connection() {}
|
||||
|
||||
/**
|
||||
* @return The handle (e.g., phone number) to which this Connection
|
||||
* is currently communicating.
|
||||
*/
|
||||
public final Uri getHandle() {
|
||||
return mHandle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The state of this Connection.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final int getState() {
|
||||
return mState;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The audio state of the call, describing how its audio is currently
|
||||
* being routed by the system. This is {@code null} if this Connection
|
||||
* does not directly know about its audio state.
|
||||
*/
|
||||
public final CallAudioState getCallAudioState() {
|
||||
return mCallAudioState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign a listener to be notified of state changes.
|
||||
*
|
||||
* @param l A listener.
|
||||
* @return This Connection.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final Connection addConnectionListener(Listener l) {
|
||||
mListeners.add(l);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a previously assigned listener that was being notified of state changes.
|
||||
*
|
||||
* @param l A Listener.
|
||||
* @return This Connection.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final Connection removeConnectionListener(Listener l) {
|
||||
mListeners.remove(l);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Play a DTMF tone in this Connection.
|
||||
*
|
||||
* @param c A DTMF character.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final void playDtmfTone(char c) {
|
||||
Log.d(TAG, "playDtmfTone " + c);
|
||||
onPlayDtmfTone(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop any DTMF tones which may be playing in this Connection.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final void stopDtmfTone() {
|
||||
Log.d(TAG, "stopDtmfTone");
|
||||
onStopDtmfTone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect this Connection. If and when the Connection can comply with
|
||||
* this request, it will transition to the {@link State#DISCONNECTED}
|
||||
* state and notify its listeners.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final void disconnect() {
|
||||
Log.d(TAG, "disconnect");
|
||||
onDisconnect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Abort this Connection. The Connection will immediately transition to
|
||||
* the {@link State#DISCONNECTED} state, and send no notifications of this
|
||||
* or any other future events.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final void abort() {
|
||||
Log.d(TAG, "abort");
|
||||
onAbort();
|
||||
}
|
||||
|
||||
/**
|
||||
* Place this Connection on hold. If and when the Connection can comply with
|
||||
* this request, it will transition to the {@link State#HOLDING}
|
||||
* state and notify its listeners.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final void hold() {
|
||||
Log.d(TAG, "hold");
|
||||
onHold();
|
||||
}
|
||||
|
||||
/**
|
||||
* Un-hold this Connection. If and when the Connection can comply with
|
||||
* this request, it will transition to the {@link State#ACTIVE}
|
||||
* state and notify its listeners.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final void unhold() {
|
||||
Log.d(TAG, "unhold");
|
||||
onUnhold();
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept a {@link State#RINGING} Connection. If and when the Connection
|
||||
* can comply with this request, it will transition to the {@link State#ACTIVE}
|
||||
* state and notify its listeners.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final void answer() {
|
||||
Log.d(TAG, "answer");
|
||||
if (mState == State.RINGING) {
|
||||
onAnswer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reject a {@link State#RINGING} Connection. If and when the Connection
|
||||
* can comply with this request, it will transition to the {@link State#ACTIVE}
|
||||
* state and notify its listeners.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final void reject() {
|
||||
Log.d(TAG, "reject");
|
||||
if (mState == State.RINGING) {
|
||||
onReject();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inform this Connection that the state of its audio output has been changed externally.
|
||||
*
|
||||
* @param state The new audio state.
|
||||
*/
|
||||
public void setAudioState(CallAudioState state) {
|
||||
Log.d(TAG, "setAudioState " + state);
|
||||
onSetAudioState(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param state An integer value from {@link State}.
|
||||
* @return A string representation of the value.
|
||||
*/
|
||||
public static String stateToString(int state) {
|
||||
switch (state) {
|
||||
case State.NEW:
|
||||
return "NEW";
|
||||
case State.RINGING:
|
||||
return "RINGING";
|
||||
case State.DIALING:
|
||||
return "DIALING";
|
||||
case State.ACTIVE:
|
||||
return "ACTIVE";
|
||||
case State.HOLDING:
|
||||
return "HOLDING";
|
||||
case State.DISCONNECTED:
|
||||
return "DISCONNECTED";
|
||||
default:
|
||||
Log.wtf(TAG, "Unknown state " + state);
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the {@link #getHandle()} property and notifies listeners.
|
||||
*
|
||||
* @param handle The new handle.
|
||||
*/
|
||||
protected void setHandle(Uri handle) {
|
||||
Log.d(TAG, "setHandle " + handle);
|
||||
// TODO: Enforce super called
|
||||
mHandle = handle;
|
||||
for (Listener l : mListeners) {
|
||||
l.onHandleChanged(this, handle);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets state to active (e.g., an ongoing call where two or more parties can actively
|
||||
* communicate).
|
||||
*/
|
||||
protected void setActive() {
|
||||
setState(State.ACTIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets state to ringing (e.g., an inbound ringing call).
|
||||
*/
|
||||
protected void setRinging() {
|
||||
setState(State.RINGING);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets state to dialing (e.g., dialing an outbound call).
|
||||
*/
|
||||
protected void setDialing() {
|
||||
setState(State.DIALING);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets state to be on hold.
|
||||
*/
|
||||
protected void setOnHold() {
|
||||
setState(State.HOLDING);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets state to disconnected. This will first notify listeners with an
|
||||
* {@link Listener#onStateChanged(Connection, int)} event, then will fire an
|
||||
* {@link Listener#onDisconnected(Connection, int, String)} event with additional
|
||||
* details.
|
||||
*
|
||||
* @param cause The reason for the disconnection, any of
|
||||
* {@link android.telephony.DisconnectCause}.
|
||||
* @param message Optional call-service-provided message about the disconnect.
|
||||
*/
|
||||
protected void setDisconnected(int cause, String message) {
|
||||
setState(State.DISCONNECTED);
|
||||
Log.d(TAG, "Disconnected with cause " + cause + " message " + message);
|
||||
for (Listener l : mListeners) {
|
||||
l.onDisconnected(this, cause, message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies this Connection and listeners that the {@link #getCallAudioState()} property
|
||||
* has a new value.
|
||||
*
|
||||
* @param state The new call audio state.
|
||||
*/
|
||||
protected void onSetAudioState(CallAudioState state) {
|
||||
// TODO: Enforce super called
|
||||
this.mCallAudioState = state;
|
||||
for (Listener l : mListeners) {
|
||||
l.onAudioStateChanged(this, state);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies this Connection and listeners of a change in the current signal levels
|
||||
* for the underlying data transport.
|
||||
*
|
||||
* @param details A {@link android.os.Bundle} containing details of the current level.
|
||||
*/
|
||||
protected void onSetSignal(Bundle details) {
|
||||
// TODO: Enforce super called
|
||||
for (Listener l : mListeners) {
|
||||
l.onSignalChanged(this, details);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies this Connection of a request to play a DTMF tone.
|
||||
*
|
||||
* @param c A DTMF character.
|
||||
*/
|
||||
protected void onPlayDtmfTone(char c) {}
|
||||
|
||||
/**
|
||||
* Notifies this Connection of a request to stop any currently playing DTMF tones.
|
||||
*/
|
||||
protected void onStopDtmfTone() {}
|
||||
|
||||
/**
|
||||
* Notifies this Connection of a request to disconnect.
|
||||
*/
|
||||
protected void onDisconnect() {}
|
||||
|
||||
/**
|
||||
* Notifies this Connection of a request to abort.
|
||||
*/
|
||||
protected void onAbort() {}
|
||||
|
||||
/**
|
||||
* Notifies this Connection of a request to hold.
|
||||
*/
|
||||
protected void onHold() {}
|
||||
|
||||
/**
|
||||
* Notifies this Connection of a request to exit a hold state.
|
||||
*/
|
||||
protected void onUnhold() {}
|
||||
|
||||
/**
|
||||
* Notifies this Connection, which is in {@link State#RINGING}, of
|
||||
* a request to accept.
|
||||
*/
|
||||
protected void onAnswer() {}
|
||||
|
||||
/**
|
||||
* Notifies this Connection, which is in {@link State#RINGING}, of
|
||||
* a request to reject.
|
||||
*/
|
||||
protected void onReject() {}
|
||||
|
||||
private void setState(int state) {
|
||||
Log.d(TAG, "setState: " + stateToString(state));
|
||||
this.mState = state;
|
||||
for (Listener l : mListeners) {
|
||||
l.onStateChanged(this, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
57
telecomm/java/android/telecomm/ConnectionRequest.java
Normal file
57
telecomm/java/android/telecomm/ConnectionRequest.java
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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 android.telecomm;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.net.Uri;
|
||||
|
||||
/**
|
||||
* Simple data container encapsulating a request to some entity to
|
||||
* create a new {@link Connection}.
|
||||
*/
|
||||
public final class ConnectionRequest {
|
||||
|
||||
// TODO: Token to limit recursive invocations
|
||||
// TODO: Consider upgrading "mHandle" to ordered list of handles, indicating a set of phone
|
||||
// numbers that would satisfy the client's needs, in order of preference
|
||||
private final Uri mHandle;
|
||||
private final Bundle mExtras;
|
||||
|
||||
public ConnectionRequest(Uri handle, Bundle extras) {
|
||||
mHandle = handle; mExtras = extras;
|
||||
}
|
||||
|
||||
/**
|
||||
* The handle (e.g., phone number) to which the {@link Connection} is to connect.
|
||||
*/
|
||||
public Uri getHandle() { return mHandle; }
|
||||
|
||||
/**
|
||||
* Application-specific extra data. Used for passing back information from an incoming
|
||||
* call {@code Intent}, and for any proprietary extensions arranged between a client
|
||||
* and servant {@code ConnectionService} which agree on a vocabulary for such data.
|
||||
*/
|
||||
public Bundle getExtras() { return mExtras; }
|
||||
|
||||
public String toString() {
|
||||
return String.format("PhoneConnectionRequest %s %s",
|
||||
mHandle == null
|
||||
? Uri.EMPTY
|
||||
: ConnectionService.toLogSafePhoneNumber(mHandle.toString()),
|
||||
mExtras == null ? "" : mExtras);
|
||||
}
|
||||
}
|
||||
345
telecomm/java/android/telecomm/ConnectionService.java
Normal file
345
telecomm/java/android/telecomm/ConnectionService.java
Normal file
@@ -0,0 +1,345 @@
|
||||
/*
|
||||
* 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 android.telecomm;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A {@link android.app.Service} that provides telephone connections to
|
||||
* processes running on an Android device.
|
||||
*/
|
||||
public abstract class ConnectionService extends CallService {
|
||||
private static final String TAG = ConnectionService.class.getSimpleName();
|
||||
|
||||
// STOPSHIP: Debug Logging should be conditional on a debug flag or use a set of
|
||||
// logging functions that make it automaticaly so.
|
||||
|
||||
// Flag controlling whether PII is emitted into the logs
|
||||
private static final boolean PII_DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
|
||||
private static final Connection NULL_CONNECTION = new Connection() {};
|
||||
|
||||
// Mappings from Connections to IDs as understood by the current CallService implementation
|
||||
private final Map<String, Connection> mConnectionById = new HashMap<>();
|
||||
private final Map<Connection, String> mIdByConnection = new HashMap<>();
|
||||
|
||||
private final Connection.Listener mConnectionListener = new Connection.Listener() {
|
||||
@Override
|
||||
public void onStateChanged(Connection c, int state) {
|
||||
String id = mIdByConnection.get(c);
|
||||
Log.d(TAG, "Adapter set state " + id + " " + Connection.stateToString(state));
|
||||
switch (state) {
|
||||
case Connection.State.ACTIVE:
|
||||
getAdapter().setActive(id);
|
||||
break;
|
||||
case Connection.State.DIALING:
|
||||
getAdapter().setDialing(id);
|
||||
break;
|
||||
case Connection.State.DISCONNECTED:
|
||||
// Handled in onDisconnected()
|
||||
break;
|
||||
case Connection.State.HOLDING:
|
||||
getAdapter().setOnHold(id);
|
||||
break;
|
||||
case Connection.State.NEW:
|
||||
// Nothing to tell Telecomm
|
||||
break;
|
||||
case Connection.State.RINGING:
|
||||
getAdapter().setRinging(id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisconnected(Connection c, int cause, String message) {
|
||||
String id = mIdByConnection.get(c);
|
||||
Log.d(TAG, "Adapter set disconnected " + cause + " " + message);
|
||||
getAdapter().setDisconnected(id, cause, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHandleChanged(Connection c, Uri newHandle) {
|
||||
// TODO: Unsupported yet
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAudioStateChanged(Connection c, CallAudioState state) {
|
||||
// TODO: Unsupported yet
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSignalChanged(Connection c, Bundle details) {
|
||||
// TODO: Unsupported yet
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyed(Connection c) {
|
||||
removeConnection(c);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public final void isCompatibleWith(final CallInfo callInfo) {
|
||||
Log.d(TAG, "isCompatibleWith " + callInfo);
|
||||
onFindSubscriptions(
|
||||
callInfo.getHandle(),
|
||||
new Response<Uri, Subscription>() {
|
||||
@Override
|
||||
public void onResult(Uri handle, Subscription... result) {
|
||||
boolean isCompatible = result.length > 0;
|
||||
Log.d(TAG, "adapter setIsCompatibleWith "
|
||||
+ callInfo.getId() + " " + isCompatible);
|
||||
getAdapter().setIsCompatibleWith(callInfo.getId(), isCompatible);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Uri handle, String reason) {
|
||||
Log.wtf(TAG, "Error in onFindSubscriptions " + callInfo.getHandle()
|
||||
+ " error: " + reason);
|
||||
getAdapter().setIsCompatibleWith(callInfo.getId(), false);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void call(final CallInfo callInfo) {
|
||||
Log.d(TAG, "call " + callInfo);
|
||||
onCreateConnections(
|
||||
new ConnectionRequest(
|
||||
callInfo.getHandle(),
|
||||
callInfo.getExtras()),
|
||||
new Response<ConnectionRequest, Connection>() {
|
||||
@Override
|
||||
public void onResult(ConnectionRequest request, Connection... result) {
|
||||
if (result.length != 1) {
|
||||
Log.d(TAG, "adapter handleFailedOutgoingCall " + callInfo);
|
||||
getAdapter().handleFailedOutgoingCall(
|
||||
callInfo.getId(),
|
||||
"Created " + result.length + " Connections, expected 1");
|
||||
for (Connection c : result) {
|
||||
c.abort();
|
||||
}
|
||||
} else {
|
||||
addConnection(callInfo.getId(), result[0]);
|
||||
Log.d(TAG, "adapter handleSuccessfulOutgoingCall "
|
||||
+ callInfo.getId());
|
||||
getAdapter().handleSuccessfulOutgoingCall(callInfo.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ConnectionRequest request, String reason) {
|
||||
getAdapter().handleFailedOutgoingCall(callInfo.getId(), reason);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void abort(String callId) {
|
||||
Log.d(TAG, "abort " + callId);
|
||||
findConnectionForAction(callId, "abort").abort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setIncomingCallId(final String callId, Bundle extras) {
|
||||
Log.d(TAG, "setIncomingCallId " + callId + " " + extras);
|
||||
onCreateIncomingConnection(
|
||||
new ConnectionRequest(
|
||||
null, // TODO: Can we obtain this from "extras"?
|
||||
extras),
|
||||
new Response<ConnectionRequest, Connection>() {
|
||||
@Override
|
||||
public void onResult(ConnectionRequest request, Connection... result) {
|
||||
if (result.length != 1) {
|
||||
Log.d(TAG, "adapter handleFailedOutgoingCall " + callId);
|
||||
getAdapter().handleFailedOutgoingCall(
|
||||
callId,
|
||||
"Created " + result.length + " Connections, expected 1");
|
||||
for (Connection c : result) {
|
||||
c.abort();
|
||||
}
|
||||
} else {
|
||||
addConnection(callId, result[0]);
|
||||
Log.d(TAG, "adapter notifyIncomingCall " + callId);
|
||||
// TODO: Uri.EMPTY is because CallInfo crashes when Parceled with a
|
||||
// null URI ... need to fix that at its cause!
|
||||
getAdapter().notifyIncomingCall(new CallInfo(
|
||||
callId,
|
||||
connectionStateToCallState(result[0].getState()),
|
||||
request.getHandle() /* result[0].getHandle() == null
|
||||
? Uri.EMPTY : result[0].getHandle() */));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ConnectionRequest request, String reason) {
|
||||
Log.d(TAG, "adapter failed setIncomingCallId " + request + " " + reason);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void answer(String callId) {
|
||||
Log.d(TAG, "answer " + callId);
|
||||
findConnectionForAction(callId, "answer").answer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void reject(String callId) {
|
||||
Log.d(TAG, "reject " + callId);
|
||||
findConnectionForAction(callId, "reject").reject();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void disconnect(String callId) {
|
||||
Log.d(TAG, "disconnect " + callId);
|
||||
findConnectionForAction(callId, "disconnect").disconnect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void hold(String callId) {
|
||||
Log.d(TAG, "hold " + callId);
|
||||
findConnectionForAction(callId, "hold").hold();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void unhold(String callId) {
|
||||
Log.d(TAG, "unhold " + callId);
|
||||
findConnectionForAction(callId, "unhold").unhold();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void playDtmfTone(String callId, char digit) {
|
||||
Log.d(TAG, "playDtmfTone " + callId + " " + Character.toString(digit));
|
||||
findConnectionForAction(callId, "playDtmfTone").playDtmfTone(digit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void stopDtmfTone(String callId) {
|
||||
Log.d(TAG, "stopDtmfTone " + callId);
|
||||
findConnectionForAction(callId, "stopDtmfTone").stopDtmfTone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onAudioStateChanged(String callId, CallAudioState audioState) {
|
||||
Log.d(TAG, "onAudioStateChanged " + callId + " " + audioState);
|
||||
findConnectionForAction(callId, "onAudioStateChanged").setAudioState(audioState);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a set of Subscriptions matching a given handle (e.g. phone number).
|
||||
*
|
||||
* @param handle A handle (e.g. phone number) with which to connect.
|
||||
* @param callback A callback for providing the result.
|
||||
*/
|
||||
public void onFindSubscriptions(
|
||||
Uri handle,
|
||||
Response<Uri, Subscription> callback) {}
|
||||
|
||||
/**
|
||||
* Create a Connection given a request.
|
||||
*
|
||||
* @param request Data encapsulating details of the desired Connection.
|
||||
* @param callback A callback for providing the result.
|
||||
*/
|
||||
public void onCreateConnections(
|
||||
ConnectionRequest request,
|
||||
Response<ConnectionRequest, Connection> callback) {}
|
||||
|
||||
/**
|
||||
* Create a Connection to match an incoming connection notification.
|
||||
*
|
||||
* @param request Data encapsulating details of the desired Connection.
|
||||
* @param callback A callback for providing the result.
|
||||
*/
|
||||
public void onCreateIncomingConnection(
|
||||
ConnectionRequest request,
|
||||
Response<ConnectionRequest, Connection> callback) {}
|
||||
|
||||
static String toLogSafePhoneNumber(String number) {
|
||||
// For unknown number, log empty string.
|
||||
if (number == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (PII_DEBUG) {
|
||||
// When PII_DEBUG is true we emit PII.
|
||||
return number;
|
||||
}
|
||||
|
||||
// Do exactly same thing as Uri#toSafeString() does, which will enable us to compare
|
||||
// sanitized phone numbers.
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (int i = 0; i < number.length(); i++) {
|
||||
char c = number.charAt(i);
|
||||
if (c == '-' || c == '@' || c == '.') {
|
||||
builder.append(c);
|
||||
} else {
|
||||
builder.append('x');
|
||||
}
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private CallState connectionStateToCallState(int connectionState) {
|
||||
switch (connectionState) {
|
||||
case Connection.State.NEW:
|
||||
return CallState.NEW;
|
||||
case Connection.State.RINGING:
|
||||
return CallState.RINGING;
|
||||
case Connection.State.DIALING:
|
||||
return CallState.DIALING;
|
||||
case Connection.State.ACTIVE:
|
||||
return CallState.ACTIVE;
|
||||
case Connection.State.HOLDING:
|
||||
return CallState.ON_HOLD;
|
||||
case Connection.State.DISCONNECTED:
|
||||
return CallState.DISCONNECTED;
|
||||
default:
|
||||
Log.wtf(TAG, "Unknown Connection.State " + connectionState);
|
||||
return CallState.NEW;
|
||||
}
|
||||
}
|
||||
|
||||
private void addConnection(String callId, Connection connection) {
|
||||
mConnectionById.put(callId, connection);
|
||||
mIdByConnection.put(connection, callId);
|
||||
connection.addConnectionListener(mConnectionListener);
|
||||
}
|
||||
|
||||
private void removeConnection(Connection connection) {
|
||||
connection.removeConnectionListener(mConnectionListener);
|
||||
mConnectionById.remove(mIdByConnection.get(connection));
|
||||
mIdByConnection.remove(connection);
|
||||
}
|
||||
|
||||
private Connection findConnectionForAction(String callId, String action) {
|
||||
if (mConnectionById.containsKey(callId)) {
|
||||
return mConnectionById.get(callId);
|
||||
}
|
||||
Log.wtf(TAG, action + " - Cannot find Connection \"" + callId + "\"");
|
||||
return NULL_CONNECTION;
|
||||
}
|
||||
}
|
||||
39
telecomm/java/android/telecomm/Response.java
Normal file
39
telecomm/java/android/telecomm/Response.java
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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 android.telecomm;
|
||||
|
||||
/**
|
||||
* Used to inform a client of asynchronously returned results.
|
||||
*/
|
||||
public interface Response<IN, OUT> {
|
||||
|
||||
/**
|
||||
* Provide a set of results.
|
||||
*
|
||||
* @param request The original request.
|
||||
* @param result The results.
|
||||
*/
|
||||
void onResult(IN request, OUT... result);
|
||||
|
||||
/**
|
||||
* Indicates the inability to provide results.
|
||||
*
|
||||
* @param request The original request.
|
||||
* @param reason The reason for the failure.
|
||||
*/
|
||||
void onError(IN request, String reason);
|
||||
}
|
||||
48
telecomm/java/android/telecomm/Subscription.java
Normal file
48
telecomm/java/android/telecomm/Subscription.java
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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 android.telecomm;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* Represents a distinct subscription, line of service or call placement method that
|
||||
* a {@link ConnectionService} can use to place phone calls.
|
||||
*/
|
||||
public class Subscription implements Parcelable {
|
||||
|
||||
public Subscription() {}
|
||||
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void writeToParcel(Parcel out, int flags) {}
|
||||
|
||||
public static final Parcelable.Creator<Subscription> CREATOR
|
||||
= new Parcelable.Creator<Subscription>() {
|
||||
public Subscription createFromParcel(Parcel in) {
|
||||
return new Subscription(in);
|
||||
}
|
||||
|
||||
public Subscription[] newArray(int size) {
|
||||
return new Subscription[size];
|
||||
}
|
||||
};
|
||||
|
||||
private Subscription(Parcel in) {}
|
||||
}
|
||||
Reference in New Issue
Block a user