blob: a4952899eb465c54175686bfcb83566562c2ffb6 [file] [log] [blame]
Tyler Gunnd5821842021-02-05 11:12:57 -08001/*
2 * Copyright (C) 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.telecom;
18
19import android.annotation.IntDef;
20import android.annotation.NonNull;
21import android.annotation.Nullable;
22import android.annotation.SystemApi;
23import android.telephony.Annotation;
24import android.telephony.CallQuality;
25import android.telephony.ims.ImsReasonInfo;
26
27import java.lang.annotation.Retention;
28import java.lang.annotation.RetentionPolicy;
29
30/**
31 * A {@link DiagnosticCall} provides a way for a {@link CallDiagnosticService} to receive diagnostic
32 * information about a mobile call on the device. The {@link CallDiagnosticService} can generate
33 * mid-call diagnostic messages using the {@link #displayDiagnosticMessage(int, CharSequence)} API
34 * which provides the user with valuable information about conditions impacting their call and
35 * corrective actions. For example, if the {@link CallDiagnosticService} determines that conditions
36 * on the call are degrading, it can inform the user that the call may soon drop and that they
37 * can try using a different calling method (e.g. VOIP or WIFI).
38 * @hide
39 */
40@SystemApi
41public abstract class DiagnosticCall {
42
43 /**
44 * @hide
45 */
46 public interface Listener {
47 void onSendDeviceToDeviceMessage(DiagnosticCall diagnosticCall, int message, int value);
48 void onDisplayDiagnosticMessage(DiagnosticCall diagnosticCall, int messageId,
49 CharSequence message);
50 void onClearDiagnosticMessage(DiagnosticCall diagnosticCall, int messageId);
51 }
52
53 /**
54 * Device to device message sent via {@link #sendDeviceToDeviceMessage(int, int)} (received via
55 * {@link #onReceiveDeviceToDeviceMessage(int, int)}) which communicates the radio access type
56 * used for the current call. Based loosely on the
57 * {@link android.telephony.TelephonyManager#getNetworkType(int)} for the call, provides a
58 * high level summary of the call radio access type.
59 * <p>
60 * Valid values:
61 * <UL>
62 * <LI>{@link #NETWORK_TYPE_LTE}</LI>
63 * <LI>{@link #NETWORK_TYPE_IWLAN}</LI>
64 * <LI>{@link #NETWORK_TYPE_NR}</LI>
65 * </UL>
66 */
67 public static final int MESSAGE_CALL_NETWORK_TYPE = 1;
68
69 /**
70 * Device to device message sent via {@link #sendDeviceToDeviceMessage(int, int)} (received via
71 * {@link #onReceiveDeviceToDeviceMessage(int, int)}) which communicates the call audio codec
72 * used for the current call. Based loosely on the {@link Connection#EXTRA_AUDIO_CODEC} for a
73 * call.
74 * <p>
75 * Valid values:
76 * <UL>
77 * <LI>{@link #AUDIO_CODEC_EVS}</LI>
78 * <LI>{@link #AUDIO_CODEC_AMR_WB}</LI>
79 * <LI>{@link #AUDIO_CODEC_AMR_NB}</LI>
80 * </UL>
81 */
82 public static final int MESSAGE_CALL_AUDIO_CODEC = 2;
83
84 /**
85 * Device to device message sent via {@link #sendDeviceToDeviceMessage(int, int)} (received via
86 * {@link #onReceiveDeviceToDeviceMessage(int, int)}) which communicates the battery state of
87 * the device. Will typically mirror battery state reported via intents such as
88 * {@link android.content.Intent#ACTION_BATTERY_LOW}.
89 * <p>
90 * Valid values:
91 * <UL>
92 * <LI>{@link #BATTERY_STATE_LOW}</LI>
93 * <LI>{@link #BATTERY_STATE_GOOD}</LI>
94 * <LI>{@link #BATTERY_STATE_CHARGING}</LI>
95 * </UL>
96 */
97 public static final int MESSAGE_DEVICE_BATTERY_STATE = 3;
98
99 /**
100 * Device to device message sent via {@link #sendDeviceToDeviceMessage(int, int)} (received via
101 * {@link #onReceiveDeviceToDeviceMessage(int, int)}) which communicates the overall network
102 * coverage as it pertains to the current call. A {@link CallDiagnosticService} should signal
103 * poor coverage if the network coverage reaches a level where there is a high probability of
104 * the call dropping as a result.
105 * <p>
106 * Valid values:
107 * <UL>
108 * <LI>{@link #COVERAGE_POOR}</LI>
109 * <LI>{@link #COVERAGE_GOOD}</LI>
110 * </UL>
111 */
112 public static final int MESSAGE_DEVICE_NETWORK_COVERAGE = 4;
113
114 /**@hide*/
115 @Retention(RetentionPolicy.SOURCE)
116 @IntDef(prefix = "MESSAGE_", value = {
117 MESSAGE_CALL_NETWORK_TYPE,
118 MESSAGE_CALL_AUDIO_CODEC,
119 MESSAGE_DEVICE_BATTERY_STATE,
120 MESSAGE_DEVICE_NETWORK_COVERAGE
121 })
122 public @interface MessageType {}
123
124 /**
125 * Used with {@link #MESSAGE_CALL_NETWORK_TYPE} to indicate an LTE network is being used for the
126 * call.
127 */
128 public static final int NETWORK_TYPE_LTE = 1;
129
130 /**
131 * Used with {@link #MESSAGE_CALL_NETWORK_TYPE} to indicate WIFI calling is in use for the call.
132 */
133 public static final int NETWORK_TYPE_IWLAN = 2;
134
135 /**
136 * Used with {@link #MESSAGE_CALL_NETWORK_TYPE} to indicate a 5G NR (new radio) network is in
137 * used for the call.
138 */
139 public static final int NETWORK_TYPE_NR = 3;
140
141 /**
142 * Used with {@link #MESSAGE_CALL_AUDIO_CODEC} to indicate call audio is using the
143 * Enhanced Voice Services (EVS) codec for the call.
144 */
145 public static final int AUDIO_CODEC_EVS = 1;
146
147 /**
148 * Used with {@link #MESSAGE_CALL_AUDIO_CODEC} to indicate call audio is using the AMR
149 * (adaptive multi-rate) WB (wide band) audio codec.
150 */
151 public static final int AUDIO_CODEC_AMR_WB = 2;
152
153 /**
154 * Used with {@link #MESSAGE_CALL_AUDIO_CODEC} to indicate call audio is using the AMR
155 * (adaptive multi-rate) NB (narrow band) audio codec.
156 */
157 public static final int AUDIO_CODEC_AMR_NB = 3;
158
159 /**
160 * Used with {@link #MESSAGE_DEVICE_BATTERY_STATE} to indicate that the battery is low.
161 */
162 public static final int BATTERY_STATE_LOW = 1;
163
164 /**
165 * Used with {@link #MESSAGE_DEVICE_BATTERY_STATE} to indicate that the battery is not low.
166 */
167 public static final int BATTERY_STATE_GOOD = 2;
168
169 /**
170 * Used with {@link #MESSAGE_DEVICE_BATTERY_STATE} to indicate that the battery is charging.
171 */
172 public static final int BATTERY_STATE_CHARGING = 3;
173
174 /**
175 * Used with {@link #MESSAGE_DEVICE_NETWORK_COVERAGE} to indicate that the coverage is poor.
176 */
177 public static final int COVERAGE_POOR = 1;
178
179 /**
180 * Used with {@link #MESSAGE_DEVICE_NETWORK_COVERAGE} to indicate that the coverage is good.
181 */
182 public static final int COVERAGE_GOOD = 2;
183
184 private Listener mListener;
185 private String mCallId;
186 private Call.Details mCallDetails;
187
188 /**
189 * @hide
190 */
191 public void setListener(@NonNull Listener listener) {
192 mListener = listener;
193 }
194
195 /**
196 * Sets the call ID for this {@link DiagnosticCall}.
197 * @param callId
198 * @hide
199 */
200 public void setCallId(@NonNull String callId) {
201 mCallId = callId;
202 }
203
204 /**
205 * @return the Telecom call ID for this {@link DiagnosticCall}.
206 * @hide
207 */
208 public @NonNull String getCallId() {
209 return mCallId;
210 }
211
212 /**
213 * Returns the latest {@link Call.Details} associated with this {@link DiagnosticCall} as
214 * reported by {@link #onCallDetailsChanged(Call.Details)}.
215 * @return The latest {@link Call.Details}.
216 */
217 public @NonNull Call.Details getCallDetails() {
218 return mCallDetails;
219 }
220
221 /**
222 * Telecom calls this method when the details of a call changes.
223 */
224 public abstract void onCallDetailsChanged(@NonNull android.telecom.Call.Details details);
225
226 /**
227 * The {@link CallDiagnosticService} implements this method to handle messages received via
228 * device to device communication.
229 * <p>
230 * See {@link #sendDeviceToDeviceMessage(int, int)} for background on device to device
231 * communication.
232 * <p>
233 * The underlying device to device communication protocol assumes that where there the two
234 * devices communicating are using a different version of the protocol, messages the recipient
235 * are not aware of are silently discarded. This means an older client talking to a new client
236 * will not receive newer messages and values sent by the new client.
237 */
238 public abstract void onReceiveDeviceToDeviceMessage(
239 @MessageType int message,
240 int value);
241
242 /**
243 * Sends a device to device message to the device on the other end of this call.
244 * <p>
245 * Device to device communication is an Android platform feature which supports low bandwidth
246 * communication between Android devices while they are in a call. The device to device
247 * communication leverages DTMF tones or RTP header extensions to pass messages. The
248 * messages are unacknowledged and sent in a best-effort manner. The protocols assume that the
249 * nature of the message are informational only and are used only to convey basic state
250 * information between devices.
251 * <p>
252 * Device to device messages are intentional simplifications of more rich indicators in the
253 * platform due to the extreme bandwidth constraints inherent with underlying device to device
254 * communication transports used by the telephony framework. Device to device communication is
255 * either accomplished by adding RFC8285 compliant RTP header extensions to the audio packets
256 * for a call, or using the DTMF digits A-D as a communication pathway. Signalling requirements
257 * for DTMF digits place a significant limitation on the amount of information which can be
258 * communicated during a call.
259 * <p>
260 * Allowed message types and values are:
261 * <ul>
262 * <li>{@link #MESSAGE_CALL_NETWORK_TYPE}
263 * <ul>
264 * <li>{@link #NETWORK_TYPE_LTE}</li>
265 * <li>{@link #NETWORK_TYPE_IWLAN}</li>
266 * <li>{@link #NETWORK_TYPE_NR}</li>
267 * </ul>
268 * </li>
269 * <li>{@link #MESSAGE_CALL_AUDIO_CODEC}
270 * <ul>
271 * <li>{@link #AUDIO_CODEC_EVS}</li>
272 * <li>{@link #AUDIO_CODEC_AMR_WB}</li>
273 * <li>{@link #AUDIO_CODEC_AMR_NB}</li>
274 * </ul>
275 * </li>
276 * <li>{@link #MESSAGE_DEVICE_BATTERY_STATE}
277 * <ul>
278 * <li>{@link #BATTERY_STATE_LOW}</li>
279 * <li>{@link #BATTERY_STATE_GOOD}</li>
280 * <li>{@link #BATTERY_STATE_CHARGING}</li>
281 * </ul>
282 * </li>
283 * <li>{@link #MESSAGE_DEVICE_NETWORK_COVERAGE}
284 * <ul>
285 * <li>{@link #COVERAGE_POOR}</li>
286 * <li>{@link #COVERAGE_GOOD}</li>
287 * </ul>
288 * </li>
289 * </ul>
290 * @param message The message type to send.
291 * @param value The message value corresponding to the type.
292 */
293 public final void sendDeviceToDeviceMessage(int message, int value) {
294 if (mListener != null) {
295 mListener.onSendDeviceToDeviceMessage(this, message, value);
296 }
297 }
298
299 /**
300 * Telecom calls this method when a GSM or CDMA call disconnects.
301 * The CallDiagnosticService can return a human readable disconnect message which will be passed
302 * to the Dialer app as the {@link DisconnectCause#getDescription()}. A dialer app typically
303 * shows this message at the termination of the call. If {@code null} is returned, the
304 * disconnect message generated by the telephony stack will be shown instead.
305 * <p>
306 * @param disconnectCause the disconnect cause for the call.
307 * @param preciseDisconnectCause the precise disconnect cause for the call.
308 * @return the disconnect message to use in place of the default Telephony message, or
309 * {@code null} if the default message will not be overridden.
310 */
311 // TODO: Wire in Telephony support for this.
312 public abstract @Nullable CharSequence onCallDisconnected(
313 @Annotation.DisconnectCauses int disconnectCause,
314 @Annotation.PreciseDisconnectCauses int preciseDisconnectCause);
315
316 /**
317 * Telecom calls this method when an IMS call disconnects and Telephony has already
318 * provided the disconnect reason info and disconnect message for the call. The
319 * {@link CallDiagnosticService} can intercept the raw IMS disconnect reason at this point and
320 * combine it with other call diagnostic information it is aware of to override the disconnect
321 * call message if desired.
322 *
323 * @param disconnectReason The {@link ImsReasonInfo} associated with the call disconnection.
324 * @return A user-readable call disconnect message to use in place of the platform-generated
325 * disconnect message, or {@code null} if the disconnect message should not be overridden.
326 */
327 // TODO: Wire in Telephony support for this.
328 public abstract @Nullable CharSequence onCallDisconnected(
329 @NonNull ImsReasonInfo disconnectReason);
330
331 /**
332 * Telecom calls this method when a {@link CallQuality} report is received from the telephony
333 * stack for a call.
334 * @param callQuality The call quality report for this call.
335 */
336 public abstract void onCallQualityReceived(@NonNull CallQuality callQuality);
337
338 /**
339 * Signals the active default dialer app to display a call diagnostic message. This can be
340 * used to report problems encountered during the span of a call.
341 * <p>
342 * The {@link CallDiagnosticService} provides a unique client-specific identifier used to
343 * identify the specific diagnostic message type.
344 * <p>
345 * The {@link CallDiagnosticService} should call {@link #clearDiagnosticMessage(int)} when the
346 * diagnostic condition has cleared.
347 * @param messageId the unique message identifier.
348 * @param message a human-readable, localized message to be shown to the user indicating a
349 * call issue which has occurred, along with potential mitigating actions.
350 */
351 public final void displayDiagnosticMessage(int messageId, @NonNull
352 CharSequence message) {
353 if (mListener != null) {
354 mListener.onDisplayDiagnosticMessage(this, messageId, message);
355 }
356 }
357
358 /**
359 * Signals to the active default dialer that the diagnostic message previously signalled using
360 * {@link #displayDiagnosticMessage(int, CharSequence)} with the specified messageId is no
361 * longer applicable (e.g. service has improved, for example.
362 * @param messageId the message identifier for a message previously shown via
363 * {@link #displayDiagnosticMessage(int, CharSequence)}.
364 */
365 public final void clearDiagnosticMessage(int messageId) {
366 if (mListener != null) {
367 mListener.onClearDiagnosticMessage(this, messageId);
368 }
369 }
370
371 /**
372 * Called by the {@link CallDiagnosticService} to update the call details for this
373 * {@link DiagnosticCall} based on an update received from Telecom.
374 * @param newDetails the new call details.
375 * @hide
376 */
377 public void handleCallUpdated(@NonNull Call.Details newDetails) {
378 mCallDetails = newDetails;
379 onCallDetailsChanged(newDetails);
380 }
381}