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
onCapabilitiesUpdated()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
registerCapabilitiesListener(@onNull CapabilitiesListener listener)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
requestCapabilities(@onNull String number)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
unregisterCapabilitiesListener(@onNull CapabilitiesListener listener)72   void unregisterCapabilitiesListener(@NonNull CapabilitiesListener listener);
73 
74   /** Gets the cached capabilities for the given number, else null */
75   @MainThread
76   @Nullable
getCapabilities(@onNull String number)77   EnrichedCallCapabilities getCapabilities(@NonNull String number);
78 
79   /** Clears any cached data, such as capabilities. */
80   @MainThread
clearCachedData()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
startCallComposerSession(@onNull String number)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
sendCallComposerData(long sessionId, @NonNull MultimediaData data)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
endCallComposerSession(long sessionId)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
sendPostCallNote(@onNull String number, @NonNull String message)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
onCapabilitiesReceived( @onNull String number, @NonNull EnrichedCallCapabilities capabilities)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      */
onEnrichedCallStateChanged()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
registerStateChangedListener(@onNull StateChangedListener listener)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
getSession(@onNull String uniqueCallId, @NonNull String number, @Nullable Filter filter)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
getSession(long sessionId)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
getAllSessionsForDisplay()173   List<String> getAllSessionsForDisplay();
174 
175   @NonNull
createIncomingCallComposerFilter()176   Filter createIncomingCallComposerFilter();
177 
178   @NonNull
createOutgoingCallComposerFilter()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      */
onHistoricalDataChanged()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
registerHistoricalDataChangedListener(@onNull HistoricalDataChangedListener listener)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
unregisterHistoricalDataChangedListener(@onNull HistoricalDataChangedListener listener)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
requestAllHistoricalData(@onNull String number, @NonNull CallDetailsEntries entries)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
getAllHistoricalData( @onNull String number, @NonNull CallDetailsEntries entries)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
hasStoredData()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
unregisterStateChangedListener(@onNull StateChangedListener listener)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
onSessionStatusUpdate(long sessionId, @NonNull String number, int state)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
onMessageUpdate(long sessionId, @NonNull String messageId, int state)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
onIncomingCallComposerData(long sessionId, @NonNull MultimediaData multimediaData)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
onIncomingPostCallData( @onNull PendingResult pendingResult, long sessionId, @NonNull MultimediaData multimediaData)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
registerVideoShareListener(@onNull VideoShareListener listener)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
unregisterVideoShareListener(@onNull VideoShareListener listener)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
onIncomingVideoShareInvite(long sessionId, @NonNull String number)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
startVideoShareSession(@onNull String number)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
acceptVideoShareSession(long sessionId)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
getVideoShareInviteSessionId(@onNull String number)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
getVideoShareSession(long sessionId)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
endVideoShareSession(long sessionId)352   void endVideoShareSession(long sessionId);
353 
354   /** Interface for filtering sessions (compatible with Predicate from Java 8) */
355   interface Filter {
test(Session session)356     boolean test(Session session);
357   }
358 }
359