Introduce new In-Call Service interface
Change-Id: I2dd8494f6e397c49180b19d1347c62edcae9b4e7 (cherry picked from commit e225fecca486858e8195eaf09d172a70fe7d632b)
This commit is contained in:
111
api/current.txt
111
api/current.txt
@@ -27850,6 +27850,62 @@ package android.system {
|
||||
|
||||
package android.telecomm {
|
||||
|
||||
public final class Call {
|
||||
method public void addListener(android.telecomm.Call.Listener);
|
||||
method public void answer();
|
||||
method public void conference();
|
||||
method public void disconnect();
|
||||
method public android.telecomm.RemoteCallVideoProvider getCallVideoProvider();
|
||||
method public java.util.List<java.lang.String> getCannedTextResponses();
|
||||
method public java.util.List<android.telecomm.Call> getChildren();
|
||||
method public android.telecomm.Call.Details getDetails();
|
||||
method public android.telecomm.Call getParent();
|
||||
method public java.lang.String getRemainingPostDialSequence();
|
||||
method public int getState();
|
||||
method public void hold();
|
||||
method public void phoneAccountClicked();
|
||||
method public void playDtmfTone(char);
|
||||
method public void postDialContinue(boolean);
|
||||
method public void reject(boolean, java.lang.String);
|
||||
method public void removeListener(android.telecomm.Call.Listener);
|
||||
method public void splitFromConference();
|
||||
method public void stopDtmfTone();
|
||||
method public void swapWithBackgroundCall();
|
||||
method public void unhold();
|
||||
field public static final int STATE_ACTIVE = 4; // 0x4
|
||||
field public static final int STATE_DIALING = 1; // 0x1
|
||||
field public static final int STATE_DISCONNECTED = 7; // 0x7
|
||||
field public static final int STATE_HOLDING = 3; // 0x3
|
||||
field public static final int STATE_NEW = 0; // 0x0
|
||||
field public static final int STATE_RINGING = 2; // 0x2
|
||||
}
|
||||
|
||||
public static class Call.Details {
|
||||
method public android.telecomm.PhoneAccount getAccount();
|
||||
method public java.lang.String getCallerDisplayName();
|
||||
method public int getCallerDisplayNamePresentation();
|
||||
method public int getCapabilities();
|
||||
method public long getConnectTimeMillis();
|
||||
method public int getDisconnectCauseCode();
|
||||
method public java.lang.String getDisconnectCauseMsg();
|
||||
method public android.telecomm.GatewayInfo getGatewayInfo();
|
||||
method public android.net.Uri getHandle();
|
||||
method public int getHandlePresentation();
|
||||
}
|
||||
|
||||
public static abstract class Call.Listener {
|
||||
ctor public Call.Listener();
|
||||
method public void onCallDestroyed(android.telecomm.Call);
|
||||
method public void onCallVideoProviderChanged(android.telecomm.Call, android.telecomm.RemoteCallVideoProvider);
|
||||
method public void onCannedTextResponsesLoaded(android.telecomm.Call, java.util.List<java.lang.String>);
|
||||
method public void onChildrenChanged(android.telecomm.Call, java.util.List<android.telecomm.Call>);
|
||||
method public void onDetailsChanged(android.telecomm.Call, android.telecomm.Call.Details);
|
||||
method public void onParentChanged(android.telecomm.Call, android.telecomm.Call);
|
||||
method public void onPostDial(android.telecomm.Call, java.lang.String);
|
||||
method public void onPostDialWait(android.telecomm.Call, java.lang.String);
|
||||
method public void onStateChanged(android.telecomm.Call, int);
|
||||
}
|
||||
|
||||
public final class CallAudioState implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
@@ -27936,8 +27992,6 @@ package android.telecomm {
|
||||
enum_constant public static final android.telecomm.CallState DISCONNECTED;
|
||||
enum_constant public static final android.telecomm.CallState NEW;
|
||||
enum_constant public static final android.telecomm.CallState ON_HOLD;
|
||||
enum_constant public static final android.telecomm.CallState POST_DIAL;
|
||||
enum_constant public static final android.telecomm.CallState POST_DIAL_WAIT;
|
||||
enum_constant public static final android.telecomm.CallState RINGING;
|
||||
}
|
||||
|
||||
@@ -28112,17 +28166,29 @@ package android.telecomm {
|
||||
field public static final android.os.Parcelable.Creator CREATOR;
|
||||
}
|
||||
|
||||
public abstract class InCallService extends android.app.Service {
|
||||
public abstract class InCallService {
|
||||
ctor protected InCallService();
|
||||
method protected abstract void addCall(android.telecomm.InCallCall);
|
||||
method protected abstract void bringToForeground(boolean);
|
||||
method protected final android.telecomm.InCallAdapter getAdapter();
|
||||
method protected void onAdapterAttached(android.telecomm.InCallAdapter);
|
||||
method protected abstract void onAudioStateChanged(android.telecomm.CallAudioState);
|
||||
method public final android.os.IBinder onBind(android.content.Intent);
|
||||
method protected abstract void setPostDial(java.lang.String, java.lang.String);
|
||||
method protected abstract void setPostDialWait(java.lang.String, java.lang.String);
|
||||
method protected abstract void updateCall(android.telecomm.InCallCall);
|
||||
method public final android.os.IBinder getBinder();
|
||||
method public android.telecomm.Phone getPhone();
|
||||
method public void onPhoneCreated(android.telecomm.Phone);
|
||||
method public void onPhoneDestroyed(android.telecomm.Phone);
|
||||
}
|
||||
|
||||
public final class Phone {
|
||||
method public final void addListener(android.telecomm.Phone.Listener);
|
||||
method public final android.telecomm.CallAudioState getAudioState();
|
||||
method public final java.util.List<android.telecomm.Call> getCalls();
|
||||
method public final void removeListener(android.telecomm.Phone.Listener);
|
||||
method public final void setAudioRoute(int);
|
||||
method public final void setMuted(boolean);
|
||||
}
|
||||
|
||||
public static abstract class Phone.Listener {
|
||||
ctor public Phone.Listener();
|
||||
method public void onAudioStateChanged(android.telecomm.Phone, android.telecomm.CallAudioState);
|
||||
method public void onBringToForeground(android.telecomm.Phone, boolean);
|
||||
method public void onCallAdded(android.telecomm.Phone, android.telecomm.Call);
|
||||
method public void onCallRemoved(android.telecomm.Phone, android.telecomm.Call);
|
||||
}
|
||||
|
||||
public final class PhoneAccount implements android.os.Parcelable {
|
||||
@@ -28151,18 +28217,17 @@ package android.telecomm {
|
||||
method public void updatePeerDimensions(int, int) throws android.os.RemoteException;
|
||||
}
|
||||
|
||||
public class RemoteCallVideoProvider implements android.os.IBinder.DeathRecipient {
|
||||
method public void binderDied();
|
||||
method public void requestCallDataUsage() throws android.os.RemoteException;
|
||||
method public void requestCameraCapabilities() throws android.os.RemoteException;
|
||||
method public void sendSessionModifyRequest(android.telecomm.VideoCallProfile) throws android.os.RemoteException;
|
||||
method public void sendSessionModifyResponse(android.telecomm.VideoCallProfile) throws android.os.RemoteException;
|
||||
method public void setCallVideoClient(android.telecomm.CallVideoClient) throws android.os.RemoteException;
|
||||
public class RemoteCallVideoProvider {
|
||||
method public void requestCallDataUsage();
|
||||
method public void requestCameraCapabilities();
|
||||
method public void sendSessionModifyRequest(android.telecomm.VideoCallProfile);
|
||||
method public void sendSessionModifyResponse(android.telecomm.VideoCallProfile);
|
||||
method public void setCallVideoClient(android.telecomm.CallVideoClient);
|
||||
method public void setCamera(java.lang.String) throws android.os.RemoteException;
|
||||
method public void setDeviceOrientation(int) throws android.os.RemoteException;
|
||||
method public void setDisplaySurface(android.view.Surface) throws android.os.RemoteException;
|
||||
method public void setPauseImage(java.lang.String) throws android.os.RemoteException;
|
||||
method public void setPreviewSurface(android.view.Surface) throws android.os.RemoteException;
|
||||
method public void setDeviceOrientation(int);
|
||||
method public void setDisplaySurface(android.view.Surface);
|
||||
method public void setPauseImage(java.lang.String);
|
||||
method public void setPreviewSurface(android.view.Surface);
|
||||
method public void setZoom(float) throws android.os.RemoteException;
|
||||
}
|
||||
|
||||
|
||||
710
telecomm/java/android/telecomm/Call.java
Normal file
710
telecomm/java/android/telecomm/Call.java
Normal file
@@ -0,0 +1,710 @@
|
||||
/*
|
||||
* 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.RemoteException;
|
||||
import android.telephony.DisconnectCause;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Represents an ongoing phone call that the in-call app should present to the user.
|
||||
*/
|
||||
public final class Call {
|
||||
/**
|
||||
* The state of a {@code Call} when newly created.
|
||||
*/
|
||||
public static final int STATE_NEW = 0;
|
||||
|
||||
/**
|
||||
* The state of an outgoing {@code Call} when dialing the remote number, but not yet connected.
|
||||
*/
|
||||
public static final int STATE_DIALING = 1;
|
||||
|
||||
/**
|
||||
* The state of an incoming {@code Call} when ringing locally, but not yet connected.
|
||||
*/
|
||||
public static final int STATE_RINGING = 2;
|
||||
|
||||
/**
|
||||
* The state of a {@code Call} when in a holding state.
|
||||
*/
|
||||
public static final int STATE_HOLDING = 3;
|
||||
|
||||
/**
|
||||
* The state of a {@code Call} when actively supporting conversation.
|
||||
*/
|
||||
public static final int STATE_ACTIVE = 4;
|
||||
|
||||
/**
|
||||
* The state of a {@code Call} when no further voice or other communication is being
|
||||
* transmitted, the remote side has been or will inevitably be informed that the {@code Call}
|
||||
* is no longer active, and the local data transport has or inevitably will release resources
|
||||
* associated with this {@code Call}.
|
||||
*/
|
||||
public static final int STATE_DISCONNECTED = 7;
|
||||
|
||||
public static class Details {
|
||||
private final Uri mHandle;
|
||||
private final int mHandlePresentation;
|
||||
private final String mCallerDisplayName;
|
||||
private final int mCallerDisplayNamePresentation;
|
||||
private final PhoneAccount mAccount;
|
||||
private final int mCapabilities;
|
||||
private final int mDisconnectCauseCode;
|
||||
private final String mDisconnectCauseMsg;
|
||||
private final long mConnectTimeMillis;
|
||||
private final GatewayInfo mGatewayInfo;
|
||||
|
||||
/**
|
||||
* @return The handle (e.g., phone number) to which the {@code Call} is currently
|
||||
* connected.
|
||||
*/
|
||||
public Uri getHandle() {
|
||||
return mHandle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The presentation requirements for the handle. See
|
||||
* {@link android.telecomm.CallPropertyPresentation} for valid values.
|
||||
*/
|
||||
public int getHandlePresentation() {
|
||||
return mHandlePresentation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The display name for the caller.
|
||||
*/
|
||||
public String getCallerDisplayName() {
|
||||
return mCallerDisplayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The presentation requirements for the caller display name. See
|
||||
* {@link android.telecomm.CallPropertyPresentation} for valid values.
|
||||
*/
|
||||
public int getCallerDisplayNamePresentation() {
|
||||
return mCallerDisplayNamePresentation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The {@code PhoneAccount} whereby the {@code Call} is currently being routed.
|
||||
*/
|
||||
public PhoneAccount getAccount() {
|
||||
return mAccount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A bitmask of the capabilities of the {@code Call}, as defined in
|
||||
* {@link CallCapabilities}.
|
||||
*/
|
||||
public int getCapabilities() {
|
||||
return mCapabilities;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return For a {@link #STATE_DISCONNECTED} {@code Call}, the disconnect cause expressed
|
||||
* as a code chosen from among those declared in {@link DisconnectCause}.
|
||||
*/
|
||||
public int getDisconnectCauseCode() {
|
||||
return mDisconnectCauseCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return For a {@link #STATE_DISCONNECTED} {@code Call}, an optional reason for
|
||||
* disconnection expressed as a free text message.
|
||||
*/
|
||||
public String getDisconnectCauseMsg() {
|
||||
return mDisconnectCauseMsg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The time the {@code Call} has been connected. This information is updated
|
||||
* periodically, but user interfaces should not rely on this to display any "call time
|
||||
* clock".
|
||||
*/
|
||||
public long getConnectTimeMillis() {
|
||||
return mConnectTimeMillis;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Information about any calling gateway the {@code Call} may be using.
|
||||
*/
|
||||
public GatewayInfo getGatewayInfo() {
|
||||
return mGatewayInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof Details) {
|
||||
Details d = (Details) o;
|
||||
return
|
||||
Objects.equals(mHandle, d.mHandle) &&
|
||||
Objects.equals(mHandlePresentation, d.mHandlePresentation) &&
|
||||
Objects.equals(mCallerDisplayName, d.mCallerDisplayName) &&
|
||||
Objects.equals(mCallerDisplayNamePresentation,
|
||||
d.mCallerDisplayNamePresentation) &&
|
||||
Objects.equals(mAccount, d.mAccount) &&
|
||||
Objects.equals(mCapabilities, d.mCapabilities) &&
|
||||
Objects.equals(mDisconnectCauseCode, d.mDisconnectCauseCode) &&
|
||||
Objects.equals(mDisconnectCauseMsg, d.mDisconnectCauseMsg) &&
|
||||
Objects.equals(mConnectTimeMillis, d.mConnectTimeMillis) &&
|
||||
Objects.equals(mGatewayInfo, d.mGatewayInfo);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return
|
||||
Objects.hashCode(mHandle) +
|
||||
Objects.hashCode(mHandlePresentation) +
|
||||
Objects.hashCode(mCallerDisplayName) +
|
||||
Objects.hashCode(mCallerDisplayNamePresentation) +
|
||||
Objects.hashCode(mAccount) +
|
||||
Objects.hashCode(mCapabilities) +
|
||||
Objects.hashCode(mDisconnectCauseCode) +
|
||||
Objects.hashCode(mDisconnectCauseMsg) +
|
||||
Objects.hashCode(mConnectTimeMillis) +
|
||||
Objects.hashCode(mGatewayInfo);
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
public Details(
|
||||
Uri handle,
|
||||
int handlePresentation,
|
||||
String callerDisplayName,
|
||||
int callerDisplayNamePresentation,
|
||||
PhoneAccount account,
|
||||
int capabilities,
|
||||
int disconnectCauseCode,
|
||||
String disconnectCauseMsg,
|
||||
long connectTimeMillis,
|
||||
GatewayInfo gatewayInfo) {
|
||||
mHandle = handle;
|
||||
mHandlePresentation = handlePresentation;
|
||||
mCallerDisplayName = callerDisplayName;
|
||||
mCallerDisplayNamePresentation = callerDisplayNamePresentation;
|
||||
mAccount = account;
|
||||
mCapabilities = capabilities;
|
||||
mDisconnectCauseCode = disconnectCauseCode;
|
||||
mDisconnectCauseMsg = disconnectCauseMsg;
|
||||
mConnectTimeMillis = connectTimeMillis;
|
||||
mGatewayInfo = gatewayInfo;
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class Listener {
|
||||
/**
|
||||
* Invoked when the state of this {@code Call} has changed. See {@link #getState()}.
|
||||
*
|
||||
* TODO(ihab): Provide previous state also?
|
||||
*
|
||||
* @param call The {@code Call} invoking this method.
|
||||
* @param state The new state of the {@code Call}.
|
||||
*/
|
||||
public void onStateChanged(Call call, int state) {}
|
||||
|
||||
/**
|
||||
* Invoked when the parent of this {@code Call} has changed. See {@link #getParent()}.
|
||||
*
|
||||
* @param call The {@code Call} invoking this method.
|
||||
* @param parent The new parent of the {@code Call}.
|
||||
*/
|
||||
public void onParentChanged(Call call, Call parent) {}
|
||||
|
||||
/**
|
||||
* Invoked when the children of this {@code Call} have changed. See {@link #getChildren()}.
|
||||
*
|
||||
* @param call The {@code Call} invoking this method.
|
||||
* @param children The new children of the {@code Call}.
|
||||
*/
|
||||
public void onChildrenChanged(Call call, List<Call> children) {}
|
||||
|
||||
/**
|
||||
* Invoked when the details of this {@code Call} have changed. See {@link #getDetails()}.
|
||||
*
|
||||
* @param call The {@code Call} invoking this method.
|
||||
* @param details A {@code Details} object describing the {@code Call}.
|
||||
*/
|
||||
public void onDetailsChanged(Call call, Details details) {}
|
||||
|
||||
/**
|
||||
* Invoked when the text messages that can be used as responses to the incoming
|
||||
* {@code Call} are loaded from the relevant database.
|
||||
* See {@link #getCannedTextResponses()}.
|
||||
*
|
||||
* @param call The {@code Call} invoking this method.
|
||||
* @param cannedTextResponses The text messages useable as responses.
|
||||
*/
|
||||
public void onCannedTextResponsesLoaded(Call call, List<String> cannedTextResponses) {}
|
||||
|
||||
/**
|
||||
* Invoked when the outgoing {@code Call} has finished dialing but is sending DTMF signals
|
||||
* that were embedded into the outgoing number.
|
||||
*
|
||||
* @param call The {@code Call} invoking this method.
|
||||
* @param remainingPostDialSequence The post-dial characters that remain to be sent.
|
||||
*/
|
||||
public void onPostDial(Call call, String remainingPostDialSequence) {}
|
||||
|
||||
/**
|
||||
* Invoked when the post-dial sequence in the outgoing {@code Call} has reached a pause
|
||||
* character. This causes the post-dial signals to stop pending user confirmation. An
|
||||
* implementation should present this choice to the user and invoke
|
||||
* {@link #postDialContinue(boolean)} when the user makes the choice.
|
||||
*
|
||||
* @param call The {@code Call} invoking this method.
|
||||
* @param remainingPostDialSequence The post-dial characters that remain to be sent.
|
||||
*/
|
||||
public void onPostDialWait(Call call, String remainingPostDialSequence) {}
|
||||
|
||||
/**
|
||||
* Invoked when the {@code RemoteCallVideoProvider} of the {@code Call} has changed.
|
||||
*
|
||||
* @param call The {@code Call} invoking this method.
|
||||
* @param callVideoProvider The {@code RemoteCallVideoProvider} associated with the
|
||||
* {@code Call}.
|
||||
*/
|
||||
|
||||
public void onCallVideoProviderChanged(Call call,
|
||||
RemoteCallVideoProvider callVideoProvider) {}
|
||||
|
||||
/**
|
||||
* Invoked when the {@code Call} is destroyed. Clients should refrain from cleaning
|
||||
* up their UI for the {@code Call} in response to state transitions. Specifically,
|
||||
* clients should not assume that a {@link #onStateChanged(Call, int)} with a state of
|
||||
* {@link #STATE_DISCONNECTED} is the final notification the {@code Call} will send. Rather,
|
||||
* clients should wait for this method to be invoked.
|
||||
*
|
||||
* @param call The {@code Call} being destroyed.
|
||||
*/
|
||||
public void onCallDestroyed(Call call) {}
|
||||
}
|
||||
|
||||
private final Phone mPhone;
|
||||
private final String mTelecommCallId;
|
||||
private final InCallAdapter mInCallAdapter;
|
||||
private Call mParent = null;
|
||||
private int mState;
|
||||
private final List<Call> mChildren = new ArrayList<>();
|
||||
private final List<Call> mUnmodifiableChildren = Collections.unmodifiableList(mChildren);
|
||||
private List<String> mCannedTextResponses = null;
|
||||
private String mRemainingPostDialSequence;
|
||||
private RemoteCallVideoProvider mCallVideoProvider;
|
||||
private Details mDetails;
|
||||
private final List<Listener> mListeners = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Obtains the post-dial sequence remaining to be emitted by this {@code Call}, if any.
|
||||
*
|
||||
* @return The remaining post-dial sequence, or {@code null} if there is no post-dial sequence
|
||||
* remaining or this {@code Call} is not in a post-dial state.
|
||||
*/
|
||||
public String getRemainingPostDialSequence() {
|
||||
return mRemainingPostDialSequence;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs this {@link #STATE_RINGING} {@code Call} to answer.
|
||||
*/
|
||||
public void answer() {
|
||||
mInCallAdapter.answerCall(mTelecommCallId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs this {@link #STATE_RINGING} {@code Call} to reject.
|
||||
*
|
||||
* @param rejectWithMessage Whether to reject with a text message.
|
||||
* @param textMessage An optional text message with which to respond.
|
||||
*/
|
||||
public void reject(boolean rejectWithMessage, String textMessage) {
|
||||
mInCallAdapter.rejectCall(mTelecommCallId, rejectWithMessage, textMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs this {@code Call} to disconnect.
|
||||
*/
|
||||
public void disconnect() {
|
||||
mInCallAdapter.disconnectCall(mTelecommCallId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs this {@code Call} to go on hold.
|
||||
*/
|
||||
public void hold() {
|
||||
mInCallAdapter.holdCall(mTelecommCallId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs this {@link #STATE_HOLDING} call to release from hold.
|
||||
*/
|
||||
public void unhold() {
|
||||
mInCallAdapter.unholdCall(mTelecommCallId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs this {@code Call} to play a dual-tone multi-frequency signaling (DTMF) tone.
|
||||
*
|
||||
* Any other currently playing DTMF tone in the specified call is immediately stopped.
|
||||
*
|
||||
* @param digit A character representing the DTMF digit for which to play the tone. This
|
||||
* value must be one of {@code '0'} through {@code '9'}, {@code '*'} or {@code '#'}.
|
||||
*/
|
||||
public void playDtmfTone(char digit) {
|
||||
mInCallAdapter.playDtmfTone(mTelecommCallId, digit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs this {@code Call} to stop any dual-tone multi-frequency signaling (DTMF) tone
|
||||
* currently playing.
|
||||
*
|
||||
* DTMF tones are played by calling {@link #playDtmfTone(char)}. If no DTMF tone is
|
||||
* currently playing, this method will do nothing.
|
||||
*/
|
||||
public void stopDtmfTone() {
|
||||
mInCallAdapter.stopDtmfTone(mTelecommCallId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs this {@code Call} to continue playing a post-dial DTMF string.
|
||||
*
|
||||
* A post-dial DTMF string is a string of digits entered after a phone number, when dialed,
|
||||
* that are immediately sent as DTMF tones to the recipient as soon as the connection is made.
|
||||
* While these tones are playing, this {@code Call} will notify listeners via
|
||||
* {@link Listener#onPostDial(Call, String)}.
|
||||
*
|
||||
* If the DTMF string contains a {@link TelecommConstants#DTMF_CHARACTER_PAUSE} symbol, this
|
||||
* {@code Call} will temporarily pause playing the tones for a pre-defined period of time.
|
||||
*
|
||||
* If the DTMF string contains a {@link TelecommConstants#DTMF_CHARACTER_WAIT} symbol, this
|
||||
* {@code Call} will pause playing the tones and notify listeners via
|
||||
* {@link Listener#onPostDialWait(Call, String)}. At this point, the in-call app
|
||||
* should display to the user an indication of this state and an affordance to continue
|
||||
* the postdial sequence. When the user decides to continue the postdial sequence, the in-call
|
||||
* app should invoke the {@link #postDialContinue(boolean)} method.
|
||||
*
|
||||
* @param proceed Whether or not to continue with the post-dial sequence.
|
||||
*/
|
||||
public void postDialContinue(boolean proceed) {
|
||||
mInCallAdapter.postDialContinue(mTelecommCallId, proceed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies this {@code Call} that the phone account user interface element was touched.
|
||||
*
|
||||
* TODO(ihab): Figure out if and how we can generalize this
|
||||
*/
|
||||
public void phoneAccountClicked() {
|
||||
mInCallAdapter.phoneAccountClicked(mTelecommCallId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs this {@code Call} to enter a conference.
|
||||
*/
|
||||
public void conference() {
|
||||
mInCallAdapter.conference(mTelecommCallId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs this {@code Call} to split from any conference call with which it may be
|
||||
* connected.
|
||||
*/
|
||||
public void splitFromConference() {
|
||||
mInCallAdapter.splitFromConference(mTelecommCallId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs this {@code Call} to swap itself with an existing background call, if one
|
||||
* such call exists.
|
||||
*/
|
||||
public void swapWithBackgroundCall() {
|
||||
mInCallAdapter.swapWithBackgroundCall(mTelecommCallId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the parent of this {@code Call} in a conference, if any.
|
||||
*
|
||||
* @return The parent {@code Call}, or {@code null} if this {@code Call} is not a
|
||||
* child of any conference {@code Call}s.
|
||||
*/
|
||||
public Call getParent() {
|
||||
return mParent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the children of this conference {@code Call}, if any.
|
||||
*
|
||||
* @return The children of this {@code Call} if this {@code Call} is a conference, or an empty
|
||||
* {@code List} otherwise.
|
||||
*/
|
||||
public List<Call> getChildren() {
|
||||
return mUnmodifiableChildren;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the state of this {@code Call}.
|
||||
*
|
||||
* @return A state value, chosen from the {@code STATE_*} constants.
|
||||
*/
|
||||
public int getState() {
|
||||
return mState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a list of canned, pre-configured message responses to present to the user as
|
||||
* ways of rejecting this {@code Call} using via a text message.
|
||||
*
|
||||
* @see #reject(boolean, String)
|
||||
*
|
||||
* @return A list of canned text message responses.
|
||||
*/
|
||||
public List<String> getCannedTextResponses() {
|
||||
return mCannedTextResponses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains an object that can be used to display video from this {@code Call}.
|
||||
*
|
||||
* @return An {@code ICallVideoProvider}.
|
||||
*/
|
||||
public RemoteCallVideoProvider getCallVideoProvider() {
|
||||
return mCallVideoProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains an object containing call details.
|
||||
*
|
||||
* @return A {@link Details} object. Depending on the state of the {@code Call}, the
|
||||
* result may be {@code null}.
|
||||
*/
|
||||
public Details getDetails() {
|
||||
return mDetails;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a listener to this {@code Call}.
|
||||
*
|
||||
* @param listener A {@code Listener}.
|
||||
*/
|
||||
public void addListener(Listener listener) {
|
||||
mListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a listener from this {@code Call}.
|
||||
*
|
||||
* @param listener A {@code Listener}.
|
||||
*/
|
||||
public void removeListener(Listener listener) {
|
||||
mListeners.remove(listener);
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
Call(Phone phone, String telecommCallId, InCallAdapter inCallAdapter) {
|
||||
mPhone = phone;
|
||||
mTelecommCallId = telecommCallId;
|
||||
mInCallAdapter = inCallAdapter;
|
||||
mState = STATE_NEW;
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
final String internalGetCallId() {
|
||||
return mTelecommCallId;
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
final void internalUpdate(InCallCall inCallCall) {
|
||||
// First, we update the internal state as far as possible before firing any updates.
|
||||
|
||||
Details details = new Details(
|
||||
inCallCall.getHandle(),
|
||||
inCallCall.getHandlePresentation(),
|
||||
inCallCall.getCallerDisplayName(),
|
||||
inCallCall.getCallerDisplayNamePresentation(),
|
||||
inCallCall.getAccount(),
|
||||
inCallCall.getCapabilities(),
|
||||
inCallCall.getDisconnectCauseCode(),
|
||||
inCallCall.getDisconnectCauseMsg(),
|
||||
inCallCall.getConnectTimeMillis(),
|
||||
inCallCall.getGatewayInfo());
|
||||
boolean detailsChanged = !Objects.equals(mDetails, details);
|
||||
if (detailsChanged) {
|
||||
mDetails = details;
|
||||
}
|
||||
|
||||
boolean cannedTextResponsesChanged = false;
|
||||
if (mCannedTextResponses == null && inCallCall.getCannedSmsResponses() != null
|
||||
&& !inCallCall.getCannedSmsResponses().isEmpty()) {
|
||||
mCannedTextResponses = Collections.unmodifiableList(inCallCall.getCannedSmsResponses());
|
||||
}
|
||||
|
||||
boolean callVideoProviderChanged = false;
|
||||
try {
|
||||
callVideoProviderChanged =
|
||||
!Objects.equals(mCallVideoProvider, inCallCall.getCallVideoProvider());
|
||||
if (callVideoProviderChanged) {
|
||||
mCallVideoProvider = inCallCall.getCallVideoProvider();
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
|
||||
int state = stateFromInCallCallState(inCallCall.getState());
|
||||
boolean stateChanged = mState != state;
|
||||
if (stateChanged) {
|
||||
mState = state;
|
||||
}
|
||||
|
||||
if (inCallCall.getParentCallId() != null) {
|
||||
mParent = mPhone.internalGetCallByTelecommId(inCallCall.getParentCallId());
|
||||
}
|
||||
|
||||
mChildren.clear();
|
||||
if (inCallCall.getChildCallIds() != null) {
|
||||
for (int i = 0; i < inCallCall.getChildCallIds().size(); i++) {
|
||||
mChildren.add(mPhone.internalGetCallByTelecommId(
|
||||
inCallCall.getChildCallIds().get(i)));
|
||||
}
|
||||
}
|
||||
|
||||
// Now we fire updates, ensuring that any client who listens to any of these notifications
|
||||
// gets the most up-to-date state.
|
||||
|
||||
if (stateChanged) {
|
||||
fireStateChanged(mState);
|
||||
}
|
||||
if (detailsChanged) {
|
||||
fireDetailsChanged(mDetails);
|
||||
}
|
||||
if (cannedTextResponsesChanged) {
|
||||
fireCannedTextResponsesLoaded(mCannedTextResponses);
|
||||
}
|
||||
if (callVideoProviderChanged) {
|
||||
fireCallVideoProviderChanged(mCallVideoProvider);
|
||||
}
|
||||
|
||||
// If we have transitioned to DISCONNECTED, that means we need to notify clients and
|
||||
// remove ourselves from the Phone. Note that we do this after completing all state updates
|
||||
// so a client can cleanly transition all their UI to the state appropriate for a
|
||||
// DISCONNECTED Call while still relying on the existence of that Call in the Phone's list.
|
||||
if (mState == STATE_DISCONNECTED) {
|
||||
fireCallDestroyed();
|
||||
mPhone.internalRemoveCall(this);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
final void internalSetPostDial(String remaining) {
|
||||
mRemainingPostDialSequence = remaining;
|
||||
firePostDial(mRemainingPostDialSequence);
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
final void internalSetPostDialWait(String remaining) {
|
||||
mRemainingPostDialSequence = remaining;
|
||||
firePostDialWait(mRemainingPostDialSequence);
|
||||
}
|
||||
|
||||
private void fireStateChanged(int newState) {
|
||||
Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
|
||||
for (int i = 0; i < listeners.length; i++) {
|
||||
listeners[i].onStateChanged(this, newState);
|
||||
}
|
||||
}
|
||||
|
||||
private void fireParentChanged(Call newParent) {
|
||||
Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
|
||||
for (int i = 0; i < listeners.length; i++) {
|
||||
listeners[i].onParentChanged(this, newParent);
|
||||
}
|
||||
}
|
||||
|
||||
private void fireChildrenChanged(List<Call> children) {
|
||||
Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
|
||||
for (int i = 0; i < listeners.length; i++) {
|
||||
listeners[i].onChildrenChanged(this, children);
|
||||
}
|
||||
}
|
||||
|
||||
private void fireDetailsChanged(Details details) {
|
||||
Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
|
||||
for (int i = 0; i < listeners.length; i++) {
|
||||
listeners[i].onDetailsChanged(this, details);
|
||||
}
|
||||
}
|
||||
|
||||
private void fireCannedTextResponsesLoaded(List<String> cannedTextResponses) {
|
||||
Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
|
||||
for (int i = 0; i < listeners.length; i++) {
|
||||
listeners[i].onCannedTextResponsesLoaded(this, cannedTextResponses);
|
||||
}
|
||||
}
|
||||
|
||||
private void fireCallVideoProviderChanged(RemoteCallVideoProvider callVideoProvider) {
|
||||
Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
|
||||
for (int i = 0; i < listeners.length; i++) {
|
||||
listeners[i].onCallVideoProviderChanged(this, callVideoProvider);
|
||||
}
|
||||
}
|
||||
|
||||
private void firePostDial(String remainingPostDialSequence) {
|
||||
Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
|
||||
for (int i = 0; i < listeners.length; i++) {
|
||||
listeners[i].onPostDial(this, remainingPostDialSequence);
|
||||
}
|
||||
}
|
||||
|
||||
private void firePostDialWait(String remainingPostDialSequence) {
|
||||
Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
|
||||
for (int i = 0; i < listeners.length; i++) {
|
||||
listeners[i].onPostDialWait(this, remainingPostDialSequence);
|
||||
}
|
||||
}
|
||||
|
||||
private void fireCallDestroyed() {
|
||||
Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
|
||||
for (int i = 0; i < listeners.length; i++) {
|
||||
listeners[i].onCallDestroyed(this);
|
||||
}
|
||||
}
|
||||
|
||||
private int stateFromInCallCallState(CallState inCallCallState) {
|
||||
switch (inCallCallState) {
|
||||
case NEW:
|
||||
return STATE_NEW;
|
||||
case DIALING:
|
||||
return STATE_DIALING;
|
||||
case RINGING:
|
||||
return STATE_RINGING;
|
||||
case ACTIVE:
|
||||
return STATE_ACTIVE;
|
||||
case ON_HOLD:
|
||||
return STATE_HOLDING;
|
||||
case DISCONNECTED:
|
||||
return STATE_DISCONNECTED;
|
||||
case ABORTED:
|
||||
return STATE_DISCONNECTED;
|
||||
default:
|
||||
Log.wtf(this, "Unrecognized CallState %s", inCallCallState);
|
||||
return STATE_NEW;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -47,22 +47,6 @@ public enum CallState {
|
||||
*/
|
||||
RINGING,
|
||||
|
||||
/**
|
||||
* Indicates that the call is active but in a "post-dial" state where Telecomm is now sending
|
||||
* some dual-tone multi-frequency signaling (DTMF) tones appended to the dialed number. Normal
|
||||
* transitions are to {@link #POST_DIAL_WAIT} when the post-dial string requires user
|
||||
* confirmation to proceed, {@link #ACTIVE} when the post-dial tones are completed, or
|
||||
* {@link #DISCONNECTED}.
|
||||
*/
|
||||
POST_DIAL,
|
||||
|
||||
/**
|
||||
* Indicates that the call was in the {@link #POST_DIAL} state but is now waiting for user
|
||||
* confirmation before the remaining digits can be sent. Normal transitions are to
|
||||
* {@link #POST_DIAL} when the user asks Telecomm to proceed with the post-dial sequence.
|
||||
*/
|
||||
POST_DIAL_WAIT,
|
||||
|
||||
/**
|
||||
* Indicates that a call is currently connected to another party and a communication channel is
|
||||
* open between them. The normal transition to this state is by the user answering a
|
||||
|
||||
@@ -241,6 +241,7 @@ public abstract class CallVideoClient {
|
||||
*
|
||||
* @param callCameraCapabilities The changed camera capabilities.
|
||||
*/
|
||||
public abstract void onHandleCameraCapabilitiesChange(CallCameraCapabilities callCameraCapabilities);
|
||||
public abstract void onHandleCameraCapabilitiesChange(
|
||||
CallCameraCapabilities callCameraCapabilities);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import com.android.internal.telecomm.IInCallAdapter;
|
||||
* Receives commands from {@link InCallService} implementations which should be executed by
|
||||
* Telecomm. When Telecomm binds to a {@link InCallService}, an instance of this class is given to
|
||||
* the in-call service through which it can manipulate live (active, dialing, ringing) calls. When
|
||||
* the in-call service is notified of new calls ({@link InCallService#addCall}), it can use the
|
||||
* the in-call service is notified of new calls, it can use the
|
||||
* given call IDs to execute commands such as {@link #answerCall} for incoming calls or
|
||||
* {@link #disconnectCall} for active calls the user would like to end. Some commands are only
|
||||
* appropriate for calls in certain states; please consult each method for such limitations.
|
||||
@@ -167,16 +167,15 @@ public final class InCallAdapter {
|
||||
* A post-dial DTMF string is a string of digits entered after a phone number, when dialed,
|
||||
* that are immediately sent as DTMF tones to the recipient as soon as the connection is made.
|
||||
* While these tones are playing, Telecomm will notify the {@link InCallService} that the call
|
||||
* is in the {@link InCallService#setPostDial(String,String)} state.
|
||||
* is in the post dial state.
|
||||
*
|
||||
* If the DTMF string contains a {@link TelecommConstants#DTMF_CHARACTER_PAUSE} symbol, Telecomm
|
||||
* will temporarily pause playing the tones for a pre-defined period of time.
|
||||
*
|
||||
* If the DTMF string contains a {@link TelecommConstants#DTMF_CHARACTER_WAIT} symbol, Telecomm
|
||||
* will pause playing the tones and notify the {@link InCallService} that the call is in the
|
||||
* {@link InCallService#setPostDialWait(String,String)} state. When the user decides to continue
|
||||
* the postdial sequence, the {@link InCallService} should invoke the
|
||||
* {@link #postDialContinue(String,boolean)} method.
|
||||
* post dial wait state. When the user decides to continue the postdial sequence, the
|
||||
* {@link InCallService} should invoke the {@link #postDialContinue(String,boolean)} method.
|
||||
*
|
||||
* @param callId The unique ID of the call for which postdial string playing should continue.
|
||||
* @param proceed Whether or not to continue with the post-dial sequence.
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package android.telecomm;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
@@ -31,11 +29,10 @@ import com.android.internal.telecomm.IInCallService;
|
||||
* This service is implemented by any app that wishes to provide the user-interface for managing
|
||||
* phone calls. Telecomm binds to this service while there exists a live (active or incoming)
|
||||
* call, and uses it to notify the in-call app of any live and and recently disconnected calls.
|
||||
* TODO(santoscordon): Needs more/better description of lifecycle once the interface is better
|
||||
* defined.
|
||||
*
|
||||
* TODO(santoscordon): What happens if two or more apps on a given device implement this interface?
|
||||
*/
|
||||
public abstract class InCallService extends Service {
|
||||
public abstract class InCallService {
|
||||
private static final int MSG_SET_IN_CALL_ADAPTER = 1;
|
||||
private static final int MSG_ADD_CALL = 2;
|
||||
private static final int MSG_UPDATE_CALL = 3;
|
||||
@@ -50,21 +47,21 @@ public abstract class InCallService extends Service {
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case MSG_SET_IN_CALL_ADAPTER:
|
||||
mAdapter = new InCallAdapter((IInCallAdapter) msg.obj);
|
||||
onAdapterAttached(mAdapter);
|
||||
mPhone = new Phone(new InCallAdapter((IInCallAdapter) msg.obj));
|
||||
onPhoneCreated(mPhone);
|
||||
break;
|
||||
case MSG_ADD_CALL:
|
||||
addCall((InCallCall) msg.obj);
|
||||
mPhone.internalAddCall((InCallCall) msg.obj);
|
||||
break;
|
||||
case MSG_UPDATE_CALL:
|
||||
updateCall((InCallCall) msg.obj);
|
||||
mPhone.internalUpdateCall((InCallCall) msg.obj);
|
||||
break;
|
||||
case MSG_SET_POST_DIAL: {
|
||||
case MSG_SET_POST_DIAL: {
|
||||
SomeArgs args = (SomeArgs) msg.obj;
|
||||
try {
|
||||
String callId = (String) args.arg1;
|
||||
String remaining = (String) args.arg2;
|
||||
setPostDial(callId, remaining);
|
||||
mPhone.internalSetPostDial(callId, remaining);
|
||||
} finally {
|
||||
args.recycle();
|
||||
}
|
||||
@@ -75,17 +72,17 @@ public abstract class InCallService extends Service {
|
||||
try {
|
||||
String callId = (String) args.arg1;
|
||||
String remaining = (String) args.arg2;
|
||||
setPostDialWait(callId, remaining);
|
||||
mPhone.internalSetPostDialWait(callId, remaining);
|
||||
} finally {
|
||||
args.recycle();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_ON_AUDIO_STATE_CHANGED:
|
||||
onAudioStateChanged((CallAudioState) msg.obj);
|
||||
mPhone.internalAudioStateChanged((CallAudioState) msg.obj);
|
||||
break;
|
||||
case MSG_BRING_TO_FOREGROUND:
|
||||
bringToForeground(msg.arg1 == 1);
|
||||
mPhone.internalBringToForeground(msg.arg1 == 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -142,85 +139,41 @@ public abstract class InCallService extends Service {
|
||||
}
|
||||
}
|
||||
|
||||
private final InCallServiceBinder mBinder;
|
||||
private Phone mPhone;
|
||||
|
||||
private InCallAdapter mAdapter;
|
||||
protected InCallService() {}
|
||||
|
||||
protected InCallService() {
|
||||
mBinder = new InCallServiceBinder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final IBinder onBind(Intent intent) {
|
||||
return mBinder;
|
||||
public final IBinder getBinder() {
|
||||
return new InCallServiceBinder();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The attached {@link InCallAdapter} if attached, or null otherwise.
|
||||
* Obtain the {@code Phone} associated with this {@code InCallService}.
|
||||
*
|
||||
* @return The {@code Phone} object associated with this {@code InCallService}, or {@code null}
|
||||
* if the {@code InCallService} is not in a state where it has an associated {@code Phone}.
|
||||
*/
|
||||
protected final InCallAdapter getAdapter() {
|
||||
return mAdapter;
|
||||
public Phone getPhone() {
|
||||
return mPhone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lifecycle callback which is called when this {@link InCallService} has been attached
|
||||
* to a {@link InCallAdapter}, indicating {@link #getAdapter()} is now safe to use.
|
||||
* Invoked when the {@code Phone} has been created. This is a signal to the in-call experience
|
||||
* to start displaying in-call information to the user. Each instance of {@code InCallService}
|
||||
* will have only one {@code Phone}, and this method will be called exactly once in the
|
||||
* lifetime of the {@code InCallService}.
|
||||
*
|
||||
* @param adapter The adapter now attached to this in-call service.
|
||||
* @param phone The {@code Phone} object associated with this {@code InCallService}.
|
||||
*/
|
||||
protected void onAdapterAttached(InCallAdapter adapter) {
|
||||
}
|
||||
public void onPhoneCreated(Phone phone) { }
|
||||
|
||||
/**
|
||||
* Indicates to the in-call app that a new call has been created and an appropriate
|
||||
* user-interface should be built and shown to notify the user.
|
||||
* Invoked when a {@code Phone} has been destroyed. This is a signal to the in-call experience
|
||||
* to stop displaying in-call information to the user. This method will be called exactly once
|
||||
* in the lifetime of the {@code InCallService}, and it will always be called after a previous
|
||||
* call to {@link #onPhoneCreated(Phone)}.
|
||||
*
|
||||
* @param call Information about the new call.
|
||||
* @param phone The {@code Phone} object associated with this {@code InCallService}.
|
||||
*/
|
||||
protected abstract void addCall(InCallCall call);
|
||||
|
||||
/**
|
||||
* Call when information about a call has changed.
|
||||
*
|
||||
* @param call Information about the new call.
|
||||
*/
|
||||
protected abstract void updateCall(InCallCall call);
|
||||
|
||||
/**
|
||||
* Indicates to the in-call app that the specified call is active but in a "post-dial" state
|
||||
* where Telecomm is now sending some dual-tone multi-frequency signaling (DTMF) tones appended
|
||||
* to the dialed number. Normal transitions are to {@link #setPostDialWait(String,String)} when
|
||||
* the post-dial string requires user confirmation to proceed, and {@link CallState#ACTIVE} when
|
||||
* the post-dial tones are completed.
|
||||
*
|
||||
* @param callId The identifier of the call changing state.
|
||||
* @param remaining The remaining postdial string to be dialed.
|
||||
*/
|
||||
protected abstract void setPostDial(String callId, String remaining);
|
||||
|
||||
/**
|
||||
* Indicates to the in-call app that the specified call was in the
|
||||
* {@link #setPostDial(String,String)} state but is now waiting for user confirmation before the
|
||||
* remaining digits can be sent. Normal transitions are to {@link #setPostDial(String,String)}
|
||||
* when the user asks Telecomm to proceed with the post-dial sequence and the in-call app
|
||||
* informs Telecomm of this by invoking {@link InCallAdapter#postDialContinue(String,boolean)}.
|
||||
*
|
||||
* @param callId The identifier of the call changing state.
|
||||
* @param remaining The remaining postdial string to be dialed.
|
||||
*/
|
||||
protected abstract void setPostDialWait(String callId, String remaining);
|
||||
|
||||
/**
|
||||
* Called when the audio state changes.
|
||||
*
|
||||
* @param audioState The new {@link CallAudioState}.
|
||||
*/
|
||||
protected abstract void onAudioStateChanged(CallAudioState audioState);
|
||||
|
||||
/**
|
||||
* Brings the in-call screen to the foreground.
|
||||
*
|
||||
* @param showDialpad If true, put up the dialpad when the screen is shown.
|
||||
*/
|
||||
protected abstract void bringToForeground(boolean showDialpad);
|
||||
public void onPhoneDestroyed(Phone phone) { }
|
||||
}
|
||||
|
||||
255
telecomm/java/android/telecomm/Phone.java
Normal file
255
telecomm/java/android/telecomm/Phone.java
Normal file
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* 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 android.telecomm;
|
||||
|
||||
import android.util.ArrayMap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A unified virtual device providing a means of voice (and other) communication on a device.
|
||||
*/
|
||||
public final class Phone {
|
||||
|
||||
public abstract static class Listener {
|
||||
/**
|
||||
* Called when the audio state changes.
|
||||
*
|
||||
* @param phone The {@code Phone} calling this method.
|
||||
* @param audioState The new {@link CallAudioState}.
|
||||
*/
|
||||
public void onAudioStateChanged(Phone phone, CallAudioState audioState) { }
|
||||
|
||||
/**
|
||||
* Called to bring the in-call screen to the foreground. The in-call experience should
|
||||
* respond immediately by coming to the foreground to inform the user of the state of
|
||||
* ongoing {@code Call}s.
|
||||
*
|
||||
* @param phone The {@code Phone} calling this method.
|
||||
* @param showDialpad If true, put up the dialpad when the screen is shown.
|
||||
*/
|
||||
public void onBringToForeground(Phone phone, boolean showDialpad) { }
|
||||
|
||||
/**
|
||||
* Called when a {@code Call} has been added to this in-call session. The in-call user
|
||||
* experience should add necessary state listeners to the specified {@code Call} and
|
||||
* immediately start to show the user information about the existence
|
||||
* and nature of this {@code Call}. Subsequent invocations of {@link #getCalls()} will
|
||||
* include this {@code Call}.
|
||||
*
|
||||
* @param phone The {@code Phone} calling this method.
|
||||
* @param call A newly added {@code Call}.
|
||||
*/
|
||||
public void onCallAdded(Phone phone, Call call) { }
|
||||
|
||||
/**
|
||||
* Called when a {@code Call} has been removed from this in-call session. The in-call user
|
||||
* experience should remove any state listeners from the specified {@code Call} and
|
||||
* immediately stop displaying any information about this {@code Call}.
|
||||
* Subsequent invocations of {@link #getCalls()} will no longer include this {@code Call}.
|
||||
*
|
||||
* @param phone The {@code Phone} calling this method.
|
||||
* @param call A newly removed {@code Call}.
|
||||
*/
|
||||
public void onCallRemoved(Phone phone, Call call) { }
|
||||
}
|
||||
|
||||
// A Map allows us to track each Call by its Telecomm-specified call ID
|
||||
private final Map<String, Call> mCallByTelecommCallId = new ArrayMap<>();
|
||||
|
||||
// A List allows us to keep the Calls in a stable iteration order so that casually developed
|
||||
// user interface components do not incur any spurious jank
|
||||
private final List<Call> mCalls = new ArrayList<>();
|
||||
|
||||
// An unmodifiable view of the above List can be safely shared with subclass implementations
|
||||
private final List<Call> mUnmodifiableCalls = Collections.unmodifiableList(mCalls);
|
||||
|
||||
private final InCallAdapter mInCallAdapter;
|
||||
|
||||
private CallAudioState mAudioState;
|
||||
|
||||
private final List<Listener> mListeners = new ArrayList<>();
|
||||
|
||||
/** {@hide} */
|
||||
Phone(InCallAdapter adapter) {
|
||||
mInCallAdapter = adapter;
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
final void internalAddCall(InCallCall inCallCall) {
|
||||
Call call = new Call(this, inCallCall.getId(), mInCallAdapter);
|
||||
mCallByTelecommCallId.put(inCallCall.getId(), call);
|
||||
mCalls.add(call);
|
||||
checkCallTree(inCallCall);
|
||||
call.internalUpdate(inCallCall);
|
||||
fireCallAdded(call);
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
final void internalRemoveCall(Call call) {
|
||||
mCallByTelecommCallId.remove(call.internalGetCallId());
|
||||
mCalls.remove(call);
|
||||
fireCallRemoved(call);
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
final void internalUpdateCall(InCallCall inCallCall) {
|
||||
Call call = mCallByTelecommCallId.get(inCallCall.getId());
|
||||
if (call != null) {
|
||||
checkCallTree(inCallCall);
|
||||
call.internalUpdate(inCallCall);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
final void internalSetPostDial(String callId, String remaining) {
|
||||
Call call = mCallByTelecommCallId.get(callId);
|
||||
if (call != null) {
|
||||
call.internalSetPostDial(remaining);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
final void internalSetPostDialWait(String callId, String remaining) {
|
||||
Call call = mCallByTelecommCallId.get(callId);
|
||||
if (call != null) {
|
||||
call.internalSetPostDialWait(remaining);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
final void internalAudioStateChanged(CallAudioState callAudioState) {
|
||||
if (!Objects.equals(mAudioState, callAudioState)) {
|
||||
mAudioState = callAudioState;
|
||||
fireAudioStateChanged(callAudioState);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
final Call internalGetCallByTelecommId(String telecommId) {
|
||||
return mCallByTelecommCallId.get(telecommId);
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
final void internalBringToForeground(boolean showDialpad) {
|
||||
fireBringToForeground(showDialpad);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a listener to this {@code Phone}.
|
||||
*
|
||||
* @param listener A {@code Listener} object.
|
||||
*/
|
||||
public final void addListener(Listener listener) {
|
||||
mListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a listener from this {@code Phone}.
|
||||
*
|
||||
* @param listener A {@code Listener} object.
|
||||
*/
|
||||
public final void removeListener(Listener listener) {
|
||||
mListeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the current list of {@code Call}s to be displayed by this in-call experience.
|
||||
*
|
||||
* @return A list of the relevant {@code Call}s.
|
||||
*/
|
||||
public final List<Call> getCalls() {
|
||||
return mUnmodifiableCalls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the microphone mute state. When this request is honored, there will be change to
|
||||
* the {@link #getAudioState()}.
|
||||
*
|
||||
* @param state {@code true} if the microphone should be muted; {@code false} otherwise.
|
||||
*/
|
||||
public final void setMuted(boolean state) {
|
||||
mInCallAdapter.mute(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the audio route (speaker, bluetooth, etc...). When this request is honored, there will
|
||||
* be change to the {@link #getAudioState()}.
|
||||
*
|
||||
* @param route The audio route to use.
|
||||
*/
|
||||
public final void setAudioRoute(int route) {
|
||||
mInCallAdapter.setAudioRoute(route);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the current phone call audio state of the {@code Phone}.
|
||||
*
|
||||
* @return An object encapsulating the audio state.
|
||||
*/
|
||||
public final CallAudioState getAudioState() {
|
||||
return mAudioState;
|
||||
}
|
||||
|
||||
private void fireCallAdded(Call call) {
|
||||
Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
|
||||
for (int i = 0; i < listeners.length; i++) {
|
||||
listeners[i].onCallAdded(this, call);
|
||||
}
|
||||
}
|
||||
|
||||
private void fireCallRemoved(Call call) {
|
||||
Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
|
||||
for (int i = 0; i < listeners.length; i++) {
|
||||
listeners[i].onCallRemoved(this, call);
|
||||
}
|
||||
}
|
||||
|
||||
private void fireAudioStateChanged(CallAudioState audioState) {
|
||||
Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
|
||||
for (int i = 0; i < listeners.length; i++) {
|
||||
listeners[i].onAudioStateChanged(this, audioState);
|
||||
}
|
||||
}
|
||||
|
||||
private void fireBringToForeground(boolean showDialpad) {
|
||||
Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
|
||||
for (int i = 0; i < listeners.length; i++) {
|
||||
listeners[i].onBringToForeground(this, showDialpad);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkCallTree(InCallCall inCallCall) {
|
||||
if (inCallCall.getParentCallId() != null &&
|
||||
!mCallByTelecommCallId.containsKey(inCallCall.getParentCallId())) {
|
||||
Log.wtf(this, "InCallCall %s has nonexistent parent %s",
|
||||
inCallCall.getId(), inCallCall.getParentCallId());
|
||||
}
|
||||
if (inCallCall.getChildCallIds() != null) {
|
||||
for (int i = 0; i < inCallCall.getChildCallIds().size(); i++) {
|
||||
if (!mCallByTelecommCallId.containsKey(inCallCall.getChildCallIds().get(i))) {
|
||||
Log.wtf(this, "InCallCall %s has nonexistent child %s",
|
||||
inCallCall.getId(), inCallCall.getChildCallIds().get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,63 +20,92 @@ import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.view.Surface;
|
||||
|
||||
import com.android.internal.telecomm.ICallVideoClient;
|
||||
import com.android.internal.telecomm.ICallVideoProvider;
|
||||
|
||||
public class RemoteCallVideoProvider implements IBinder.DeathRecipient {
|
||||
public class RemoteCallVideoProvider {
|
||||
private final ICallVideoProvider mCallVideoProvider;
|
||||
|
||||
private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
|
||||
@Override
|
||||
public void binderDied() {
|
||||
mCallVideoProvider.asBinder().unlinkToDeath(this, 0);
|
||||
}
|
||||
};
|
||||
|
||||
/** {@hide} */
|
||||
RemoteCallVideoProvider(ICallVideoProvider callVideoProvider) throws RemoteException {
|
||||
mCallVideoProvider = callVideoProvider;
|
||||
mCallVideoProvider.asBinder().linkToDeath(this, 0);
|
||||
mCallVideoProvider.asBinder().linkToDeath(mDeathRecipient, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void binderDied() {
|
||||
mCallVideoProvider.asBinder().unlinkToDeath(this, 0);
|
||||
}
|
||||
|
||||
public void setCallVideoClient(CallVideoClient callVideoClient) throws RemoteException {
|
||||
mCallVideoProvider.setCallVideoClient(callVideoClient.getBinder());
|
||||
public void setCallVideoClient(CallVideoClient callVideoClient) {
|
||||
try {
|
||||
mCallVideoProvider.setCallVideoClient(callVideoClient.getBinder());
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
}
|
||||
|
||||
public void setCamera(String cameraId) throws RemoteException {
|
||||
mCallVideoProvider.setCamera(cameraId);
|
||||
}
|
||||
|
||||
public void setPreviewSurface(Surface surface) throws RemoteException {
|
||||
mCallVideoProvider.setPreviewSurface(surface);
|
||||
public void setPreviewSurface(Surface surface) {
|
||||
try {
|
||||
mCallVideoProvider.setPreviewSurface(surface);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
}
|
||||
|
||||
public void setDisplaySurface(Surface surface) throws RemoteException {
|
||||
mCallVideoProvider.setDisplaySurface(surface);
|
||||
public void setDisplaySurface(Surface surface) {
|
||||
try {
|
||||
mCallVideoProvider.setDisplaySurface(surface);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
}
|
||||
|
||||
public void setDeviceOrientation(int rotation) throws RemoteException {
|
||||
mCallVideoProvider.setDeviceOrientation(rotation);
|
||||
public void setDeviceOrientation(int rotation) {
|
||||
try {
|
||||
mCallVideoProvider.setDeviceOrientation(rotation);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
}
|
||||
|
||||
public void setZoom(float value) throws RemoteException {
|
||||
mCallVideoProvider.setZoom(value);
|
||||
}
|
||||
|
||||
public void sendSessionModifyRequest(VideoCallProfile requestProfile) throws RemoteException {
|
||||
mCallVideoProvider.sendSessionModifyRequest(requestProfile);
|
||||
public void sendSessionModifyRequest(VideoCallProfile requestProfile) {
|
||||
try {
|
||||
mCallVideoProvider.sendSessionModifyRequest(requestProfile);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
}
|
||||
|
||||
public void sendSessionModifyResponse(VideoCallProfile responseProfile) throws RemoteException {
|
||||
mCallVideoProvider.sendSessionModifyResponse(responseProfile);
|
||||
public void sendSessionModifyResponse(VideoCallProfile responseProfile) {
|
||||
try {
|
||||
mCallVideoProvider.sendSessionModifyResponse(responseProfile);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
}
|
||||
|
||||
public void requestCameraCapabilities() throws RemoteException {
|
||||
mCallVideoProvider.requestCameraCapabilities();
|
||||
public void requestCameraCapabilities() {
|
||||
try {
|
||||
mCallVideoProvider.requestCameraCapabilities();
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
}
|
||||
|
||||
public void requestCallDataUsage() throws RemoteException {
|
||||
mCallVideoProvider.requestCallDataUsage();
|
||||
public void requestCallDataUsage() {
|
||||
try {
|
||||
mCallVideoProvider.requestCallDataUsage();
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
}
|
||||
|
||||
public void setPauseImage(String uri) throws RemoteException {
|
||||
mCallVideoProvider.setPauseImage(uri);
|
||||
public void setPauseImage(String uri) {
|
||||
try {
|
||||
mCallVideoProvider.setPauseImage(uri);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user