diff options
author | Ihab Awad <ihab@google.com> | 2014-05-16 10:22:16 -0700 |
---|---|---|
committer | Ihab Awad <ihab@google.com> | 2014-05-18 18:58:28 -0700 |
commit | 542e0ea8bfa60f09c33e4be366adf8681c25d0bf (patch) | |
tree | c14780ca73f0a2638138ae8a7a2ec1b2f26e80b9 /telecomm | |
parent | c9ee304c91b5572f0c1cd95e9bd1e4a84e28587d (diff) | |
download | frameworks_base-542e0ea8bfa60f09c33e4be366adf8681c25d0bf.zip frameworks_base-542e0ea8bfa60f09c33e4be366adf8681c25d0bf.tar.gz frameworks_base-542e0ea8bfa60f09c33e4be366adf8681c25d0bf.tar.bz2 |
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
Diffstat (limited to 'telecomm')
-rw-r--r-- | telecomm/java/android/telecomm/Connection.java | 412 | ||||
-rw-r--r-- | telecomm/java/android/telecomm/ConnectionRequest.java | 57 | ||||
-rw-r--r-- | telecomm/java/android/telecomm/ConnectionService.java | 345 | ||||
-rw-r--r-- | telecomm/java/android/telecomm/Response.java | 39 | ||||
-rw-r--r-- | telecomm/java/android/telecomm/Subscription.java | 48 |
5 files changed, 901 insertions, 0 deletions
diff --git a/telecomm/java/android/telecomm/Connection.java b/telecomm/java/android/telecomm/Connection.java new file mode 100644 index 0000000..6b7463c --- /dev/null +++ b/telecomm/java/android/telecomm/Connection.java @@ -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); + } + } +} diff --git a/telecomm/java/android/telecomm/ConnectionRequest.java b/telecomm/java/android/telecomm/ConnectionRequest.java new file mode 100644 index 0000000..c1f1871 --- /dev/null +++ b/telecomm/java/android/telecomm/ConnectionRequest.java @@ -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); + } +} diff --git a/telecomm/java/android/telecomm/ConnectionService.java b/telecomm/java/android/telecomm/ConnectionService.java new file mode 100644 index 0000000..aba4579 --- /dev/null +++ b/telecomm/java/android/telecomm/ConnectionService.java @@ -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; + } +}
\ No newline at end of file diff --git a/telecomm/java/android/telecomm/Response.java b/telecomm/java/android/telecomm/Response.java new file mode 100644 index 0000000..14f8340 --- /dev/null +++ b/telecomm/java/android/telecomm/Response.java @@ -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); +} diff --git a/telecomm/java/android/telecomm/Subscription.java b/telecomm/java/android/telecomm/Subscription.java new file mode 100644 index 0000000..f187f4d --- /dev/null +++ b/telecomm/java/android/telecomm/Subscription.java @@ -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) {} +} |