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