1 /* 2 * Copyright (C) 2016 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 17 package com.android.dialer.enrichedcall; 18 19 import android.content.BroadcastReceiver.PendingResult; 20 import android.support.annotation.MainThread; 21 import android.support.annotation.NonNull; 22 import android.support.annotation.Nullable; 23 import com.android.dialer.calldetails.CallDetailsEntries; 24 import com.android.dialer.calldetails.CallDetailsEntries.CallDetailsEntry; 25 import com.android.dialer.enrichedcall.historyquery.proto.HistoryResult; 26 import com.android.dialer.enrichedcall.videoshare.VideoShareListener; 27 import com.android.dialer.enrichedcall.videoshare.VideoShareSession; 28 import com.android.dialer.multimedia.MultimediaData; 29 import java.util.List; 30 import java.util.Map; 31 32 /** Performs all enriched calling logic. */ 33 public interface EnrichedCallManager { 34 35 int POST_CALL_NOTE_MAX_CHAR = 60; 36 37 /** Receives updates when enriched call capabilities are ready. */ 38 interface CapabilitiesListener { 39 40 /** Callback fired when the capabilities are updated. */ 41 @MainThread 42 void onCapabilitiesUpdated(); 43 } 44 45 /** 46 * Registers the given {@link CapabilitiesListener}. 47 * 48 * <p>As a result of this method, the listener will receive a call to {@link 49 * CapabilitiesListener#onCapabilitiesUpdated()} after a call to {@link 50 * #requestCapabilities(String)}. 51 */ 52 @MainThread 53 void registerCapabilitiesListener(@NonNull CapabilitiesListener listener); 54 55 /** 56 * Starts an asynchronous process to get enriched call capabilities of the given number. 57 * 58 * <p>Registered listeners will receive a call to {@link 59 * CapabilitiesListener#onCapabilitiesUpdated()} on completion. 60 * 61 * @param number the remote number in any format 62 */ 63 @MainThread 64 void requestCapabilities(@NonNull String number); 65 66 /** 67 * Unregisters the given {@link CapabilitiesListener}. 68 * 69 * <p>As a result of this method, the listener will not receive capabilities of the given number. 70 */ 71 @MainThread 72 void unregisterCapabilitiesListener(@NonNull CapabilitiesListener listener); 73 74 /** Gets the cached capabilities for the given number, else null */ 75 @MainThread 76 @Nullable 77 EnrichedCallCapabilities getCapabilities(@NonNull String number); 78 79 /** Clears any cached data, such as capabilities. */ 80 @MainThread 81 void clearCachedData(); 82 83 /** 84 * Starts a call composer session with the given remote number. 85 * 86 * @param number the remote number in any format 87 * @return the id for the started session, or {@link Session#NO_SESSION_ID} if the session fails 88 */ 89 @MainThread 90 long startCallComposerSession(@NonNull String number); 91 92 /** 93 * Sends the given information through an open enriched call session. As per the enriched calling 94 * spec, up to two messages are sent: the first is an enriched call data message that optionally 95 * includes the subject and the second is the optional image data message. 96 * 97 * @param sessionId the id for the session. See {@link #startCallComposerSession(String)} 98 * @param data the {@link MultimediaData} 99 * @throws IllegalArgumentException if there's no open session with the given number 100 * @throws IllegalStateException if the session isn't in the {@link Session#STATE_STARTED} state 101 */ 102 @MainThread 103 void sendCallComposerData(long sessionId, @NonNull MultimediaData data); 104 105 /** 106 * Ends the given call composer session. Ending a session means that the call composer session 107 * will be closed. 108 * 109 * @param sessionId the id of the session to end 110 */ 111 @MainThread 112 void endCallComposerSession(long sessionId); 113 114 /** 115 * Sends a post call note to the given number. 116 * 117 * @throws IllegalArgumentException if message is longer than {@link #POST_CALL_NOTE_MAX_CHAR} 118 * characters 119 */ 120 @MainThread 121 void sendPostCallNote(@NonNull String number, @NonNull String message); 122 123 /** 124 * Called once the capabilities are available for a corresponding call to {@link 125 * #requestCapabilities(String)}. 126 * 127 * @param number the remote number in any format 128 * @param capabilities the supported capabilities 129 */ 130 @MainThread 131 void onCapabilitiesReceived( 132 @NonNull String number, @NonNull EnrichedCallCapabilities capabilities); 133 134 /** Receives updates when the state of an enriched call changes. */ 135 interface StateChangedListener { 136 137 /** 138 * Callback fired when state changes. Listeners should call {@link #getSession(long)} or {@link 139 * #getSession(String, String, Filter)} to retrieve the new state. 140 */ 141 void onEnrichedCallStateChanged(); 142 } 143 144 /** 145 * Registers the given {@link StateChangedListener}. 146 * 147 * <p>As a result of this method, the listener will receive updates when the state of any enriched 148 * call changes. 149 */ 150 @MainThread 151 void registerStateChangedListener(@NonNull StateChangedListener listener); 152 153 /** 154 * Returns the {@link Session} for the given unique call id, falling back to the number. If a 155 * filter is provided, it will be applied to both the uniqueCalId and number lookups. 156 */ 157 @MainThread 158 @Nullable 159 Session getSession(@NonNull String uniqueCallId, @NonNull String number, @Nullable Filter filter); 160 161 /** Returns the {@link Session} for the given sessionId, or {@code null} if no session exists. */ 162 @MainThread 163 @Nullable 164 Session getSession(long sessionId); 165 166 /** 167 * Returns a list containing viewable string representations of all existing sessions. 168 * 169 * <p>Intended for debug display purposes only. 170 */ 171 @MainThread 172 @NonNull 173 List<String> getAllSessionsForDisplay(); 174 175 @NonNull 176 Filter createIncomingCallComposerFilter(); 177 178 @NonNull 179 Filter createOutgoingCallComposerFilter(); 180 181 /** Receives updates when the state of an historical data changes. */ 182 interface HistoricalDataChangedListener { 183 184 /** 185 * Callback fired when historical data changes. Listeners should call {@link 186 * #getAllHistoricalData(String, CallDetailsEntries)} to retrieve the new data. 187 */ 188 void onHistoricalDataChanged(); 189 } 190 191 /** 192 * Registers the given {@link HistoricalDataChangedListener}. 193 * 194 * <p>As a result of this method, the listener will receive updates when the state of any enriched 195 * call historical data changes. 196 */ 197 @MainThread 198 void registerHistoricalDataChangedListener(@NonNull HistoricalDataChangedListener listener); 199 200 /** 201 * Unregisters the given {@link HistoricalDataChangedListener}. 202 * 203 * <p>As a result of this method, the listener will not receive updates when the state of enriched 204 * call historical data changes. 205 */ 206 @MainThread 207 void unregisterHistoricalDataChangedListener(@NonNull HistoricalDataChangedListener listener); 208 209 /** 210 * Starts an asynchronous process to get all historical data for the given number and set of 211 * {@link CallDetailsEntries}. 212 */ 213 @MainThread 214 void requestAllHistoricalData(@NonNull String number, @NonNull CallDetailsEntries entries); 215 216 /** 217 * Returns a mapping of enriched call data for all of the given {@link CallDetailsEntries}, which 218 * should not be modified. A {@code null} return indicates that clients should call {@link 219 * #requestAllHistoricalData(String, CallDetailsEntries)}. 220 * 221 * <p>The mapping is created by finding the HistoryResults whose timestamps occurred during or 222 * close after a CallDetailsEntry. A CallDetailsEntry can have multiple HistoryResults in the 223 * event that both a CallComposer message and PostCall message were sent for the same call. 224 */ 225 @Nullable 226 @MainThread 227 Map<CallDetailsEntry, List<HistoryResult>> getAllHistoricalData( 228 @NonNull String number, @NonNull CallDetailsEntries entries); 229 230 /** Returns true if any enriched calls have been made or received. */ 231 @MainThread 232 boolean hasStoredData(); 233 234 /** 235 * Unregisters the given {@link StateChangedListener}. 236 * 237 * <p>As a result of this method, the listener will not receive updates when the state of enriched 238 * calls changes. 239 */ 240 @MainThread 241 void unregisterStateChangedListener(@NonNull StateChangedListener listener); 242 243 /** 244 * Called when the status of an enriched call session changes. 245 * 246 * 247 * @throws IllegalArgumentException if the state is invalid 248 */ 249 @MainThread 250 void onSessionStatusUpdate(long sessionId, @NonNull String number, int state); 251 252 /** 253 * Called when the status of an enriched call message updates. 254 * 255 * 256 * @throws IllegalArgumentException if the state is invalid 257 * @throws IllegalStateException if there's no session for the given id 258 */ 259 @MainThread 260 void onMessageUpdate(long sessionId, @NonNull String messageId, int state); 261 262 /** 263 * Called when call composer data arrives for the given session. 264 * 265 * @throws IllegalStateException if there's no session for the given id 266 */ 267 @MainThread 268 void onIncomingCallComposerData(long sessionId, @NonNull MultimediaData multimediaData); 269 270 /** 271 * Called when post call data arrives for the given session. 272 * 273 * @param pendingResult PendingResult form a broadcast receiver. The broadcast might be received 274 * when dialer is not in the foreground, and can not start {@link 275 * com.android.dialer.app.calllog.CallLogNotificationsService} to handle the event. The 276 * pendingResult allows dialer to hold on to resources when the event is handled in a 277 * background thread. TODO(a bug): migrate CallLogNotificationsService to a 278 * JobIntentService so it can be used in the background. 279 * @throws IllegalStateException if there's no session for the given id 280 */ 281 @MainThread 282 void onIncomingPostCallData( 283 @NonNull PendingResult pendingResult, long sessionId, @NonNull MultimediaData multimediaData); 284 285 /** 286 * Registers the given {@link VideoShareListener}. 287 * 288 * <p>As a result of this method, the listener will receive updates when any video share state 289 * changes. 290 */ 291 @MainThread 292 void registerVideoShareListener(@NonNull VideoShareListener listener); 293 294 /** 295 * Unregisters the given {@link VideoShareListener}. 296 * 297 * <p>As a result of this method, the listener will not receive updates when any video share state 298 * changes. 299 */ 300 @MainThread 301 void unregisterVideoShareListener(@NonNull VideoShareListener listener); 302 303 /** 304 * Called when an incoming video share invite is received. 305 * 306 * @return whether or not the invite was accepted by the manager (rejected when disabled) 307 */ 308 @MainThread 309 boolean onIncomingVideoShareInvite(long sessionId, @NonNull String number); 310 311 /** 312 * Starts a video share session with the given remote number. 313 * 314 * @param number the remote number in any format 315 * @return the id for the started session, or {@link Session#NO_SESSION_ID} if the session fails 316 */ 317 @MainThread 318 long startVideoShareSession(@NonNull String number); 319 320 /** 321 * Accepts a video share session invite. 322 * 323 * @param sessionId the session to accept 324 * @return whether or not accepting the session succeeded 325 */ 326 @MainThread 327 boolean acceptVideoShareSession(long sessionId); 328 329 /** 330 * Retrieve the session id for an incoming video share invite. 331 * 332 * @param number the remote number in any format 333 * @return the id for the session invite, or {@link Session#NO_SESSION_ID} if there is no invite 334 */ 335 @MainThread 336 long getVideoShareInviteSessionId(@NonNull String number); 337 338 /** 339 * Returns the {@link VideoShareSession} for the given sessionId, or {@code null} if no session 340 * exists. 341 */ 342 @MainThread 343 @Nullable 344 VideoShareSession getVideoShareSession(long sessionId); 345 346 /** 347 * Ends the given video share session. 348 * 349 * @param sessionId the id of the session to end 350 */ 351 @MainThread 352 void endVideoShareSession(long sessionId); 353 354 /** Interface for filtering sessions (compatible with Predicate from Java 8) */ 355 interface Filter { 356 boolean test(Session session); 357 } 358 } 359