• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2015, Motorola Mobility LLC
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *     - Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     - Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *     - Neither the name of Motorola Mobility nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MOTOROLA MOBILITY LLC BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
26  * DAMAGE.
27  */
28 
29 package com.android.service.ims;
30 
31 import java.util.Set;
32 import java.util.HashMap;
33 import java.util.Iterator;
34 import java.util.Map;
35 import java.util.List;
36 import java.util.ArrayList;
37 import android.os.RemoteException;
38 import android.content.Context;
39 import android.os.Handler;
40 import android.os.Message;
41 import android.os.HandlerThread;
42 import android.os.Looper;
43 import android.telephony.PhoneNumberUtils;
44 
45 import com.android.ims.internal.uce.presence.PresCmdStatus;
46 
47 import com.android.ims.internal.Logger;
48 import com.android.ims.RcsManager.ResultCode;
49 import com.android.ims.RcsPresenceInfo;
50 import com.android.ims.IRcsPresenceListener;
51 
52 import com.android.service.ims.presence.PresenceTask;
53 import com.android.service.ims.presence.PresenceCapabilityTask;
54 import com.android.service.ims.presence.PresenceAvailabilityTask;
55 
56 /**
57  * TaskManager
58  */
59 public class TaskManager{
60     /*
61      * The logger
62      */
63     private Logger logger = Logger.getLogger(this.getClass().getName());
64 
65     private static TaskManager sTaskManager = null;
66 
67     private int mTaskId = 0;
68 
69     public final static int TASK_TYPE_GET_CAPABILITY   = 1;
70     public final static int TASK_TYPE_GET_AVAILABILITY = 2;
71     public final static int TASK_TYPE_PUBLISH          = 3;
72 
73     private Map<String, Task> mTaskMap;
74 
75     private final Object mSyncObj = new Object();
76 
77     private static final int TASK_MANAGER_ON_TERMINATED = 1;
78     private static final int TASK_MANAGER_ON_TIMEOUT = 2;
79 
80     private static MessageHandler sMsgHandler;
81 
TaskManager()82     public TaskManager(){
83         logger.debug("TaskManager created.");
84         mTaskMap = new HashMap<String, Task>();
85 
86         HandlerThread messageHandlerThread = new HandlerThread("MessageHandler",
87                 android.os.Process.THREAD_PRIORITY_BACKGROUND);
88 
89         messageHandlerThread.start();
90         Looper messageHandlerLooper = messageHandlerThread.getLooper();
91         sMsgHandler = new MessageHandler(messageHandlerLooper);
92     }
93 
getDefault()94     public static synchronized TaskManager getDefault(){
95         if(sTaskManager == null){
96             sTaskManager = new TaskManager();
97         }
98 
99         return sTaskManager;
100     }
101 
generateTaskId()102     public synchronized int generateTaskId(){
103         return mTaskId++;
104     }
105 
putTask(int taskId, Task task)106     public void putTask(int taskId, Task task){
107         synchronized (mSyncObj){
108             putTaskInternal(taskId, task);
109         }
110     }
111 
putTaskInternal(int taskId, Task task)112     private synchronized void putTaskInternal(int taskId, Task task){
113         Task sameKeyTask = mTaskMap.put(String.valueOf(taskId), task);
114 
115         logger.debug("Added Task: " + task + "Original same key task:" + sameKeyTask);
116     }
117 
addCapabilityTask(Context context, String[] contacts, IRcsPresenceListener listener, long timeout)118     public int addCapabilityTask(Context context, String[] contacts,
119             IRcsPresenceListener listener, long timeout){
120         int taskId = TaskManager.getDefault().generateTaskId();
121         synchronized (mSyncObj){
122             Task task = new PresenceCapabilityTask(context, taskId, TASK_TYPE_GET_CAPABILITY,
123                     listener, contacts, timeout);
124             putTaskInternal(taskId, task);
125         }
126 
127         return taskId;
128     }
129 
addAvailabilityTask(String contact, IRcsPresenceListener listener)130     public int addAvailabilityTask(String contact, IRcsPresenceListener listener){
131         int taskId = TaskManager.getDefault().generateTaskId();
132         synchronized (mSyncObj){
133             String[] contacts = new String[1];
134             contacts[0] = contact;
135             Task task = new PresenceAvailabilityTask(taskId, TASK_TYPE_GET_AVAILABILITY,
136                     listener, contacts);
137             putTaskInternal(taskId, task);
138         }
139 
140         return taskId;
141     }
142 
addPublishTask(String contact, IRcsPresenceListener listener)143     public int addPublishTask(String contact, IRcsPresenceListener listener){
144         int taskId = TaskManager.getDefault().generateTaskId();
145         synchronized (mSyncObj){
146             String[] contacts = new String[1];
147             contacts[0] = contact;
148             Task task = new PresenceTask(taskId, TASK_TYPE_PUBLISH, listener, contacts);
149             putTaskInternal(taskId, task);
150         }
151 
152         return taskId;
153     }
154 
155     // If need to call getTask in this class please add another one getTaskInternal
getTask(int taskId)156     public Task getTask(int taskId){
157         synchronized (mSyncObj){
158             return mTaskMap.get(String.valueOf(taskId));
159         }
160     }
161 
removeTask(int taskId)162     public void removeTask(int taskId){
163         synchronized (mSyncObj){
164             Task task = mTaskMap.remove(String.valueOf(taskId));
165             if(task instanceof PresenceCapabilityTask){
166                 ((PresenceCapabilityTask)task).cancelTimer();
167             }
168             logger.debug("Removed Task: " + task);
169         }
170     }
171 
getTaskByRequestId(int sipRequestId)172     public Task getTaskByRequestId(int sipRequestId){
173         synchronized (mSyncObj){
174             Set<String> keys= mTaskMap.keySet();
175             if(keys == null){
176                 logger.debug("getTaskByRequestId keys=null");
177                 return null;
178             }
179 
180             for(String key:keys){
181                 if(mTaskMap.get(key).mSipRequestId == sipRequestId){
182                     logger.debug("getTaskByRequestId, sipRequestId=" + sipRequestId +
183                             " task=" + mTaskMap.get(key));
184                     return mTaskMap.get(key);
185                 }
186             }
187         }
188 
189         logger.debug("getTaskByRequestId, sipRequestId=" + sipRequestId + " task=null");
190         return null;
191     }
192 
onTerminated(String contact)193     public void onTerminated(String contact){ // for single number capability polling
194         if(contact == null){
195             return;
196         }
197 
198         synchronized (mSyncObj){
199             Set<String> keys= mTaskMap.keySet();
200             if(keys == null){
201                 logger.debug("onTerminated keys is null");
202                 return;
203             }
204 
205             for(String key:keys){
206                 Task task = mTaskMap.get(key);
207                 if(task == null){
208                     continue;
209                 }
210 
211                 if(task instanceof PresenceCapabilityTask){
212                     PresenceCapabilityTask capabilityTask = (PresenceCapabilityTask)task;
213                     if(capabilityTask.mContacts != null && capabilityTask.mContacts[0] != null &&
214                             PhoneNumberUtils.compare(contact, capabilityTask.mContacts[0])){
215                         if(!capabilityTask.isWaitingForNotify()){
216                             logger.debug("onTerminated the tesk is not waiting for NOTIFY yet");
217                             continue;
218                         }
219 
220                         MessageData messageData = new MessageData();
221                         messageData.mTask = capabilityTask;
222                         messageData.mReason = null;
223 
224                         Message notifyMessage = sMsgHandler.obtainMessage(
225                                 TASK_MANAGER_ON_TERMINATED,
226                                 messageData);
227                         sMsgHandler.sendMessage(notifyMessage);
228                     }
229                 }
230             }
231         }
232     }
233 
onTerminated(int requestId, String reason)234     public void onTerminated(int requestId, String reason){
235         logger.debug("onTerminated requestId=" + requestId + " reason=" + reason);
236 
237         Task task = getTaskByRequestId(requestId);
238         if(task == null){
239             logger.debug("onTerminated Can't find request " + requestId);
240             return;
241         }
242 
243         synchronized (mSyncObj){
244             if(task instanceof PresenceCapabilityTask){
245                 MessageData messageData = new MessageData();
246                 messageData.mTask = (PresenceCapabilityTask)task;
247                 messageData.mReason = reason;
248 
249                 Message notifyMessage = sMsgHandler.obtainMessage(TASK_MANAGER_ON_TERMINATED,
250                         messageData);
251                 sMsgHandler.sendMessage(notifyMessage);
252             }
253         }
254     }
255 
onTimeout(int taskId)256     public void onTimeout(int taskId){
257         logger.debug("onTimeout taskId=" + taskId);
258 
259         Task task = getTask(taskId);
260         if(task == null){
261             logger.debug("onTimeout task = null");
262             return;
263         }
264         synchronized (mSyncObj){
265             if(task instanceof PresenceCapabilityTask){
266                 MessageData messageData = new MessageData();
267                 messageData.mTask = (PresenceCapabilityTask)task;
268                 messageData.mReason = null;
269 
270                 Message timeoutMessage = sMsgHandler.obtainMessage(TASK_MANAGER_ON_TIMEOUT,
271                         messageData);
272                 sMsgHandler.sendMessage(timeoutMessage);
273             }else{
274                 logger.debug("not PresenceCapabilityTask, taskId=" + taskId);
275             }
276         }
277     }
278 
279     public class MessageData{
280         public PresenceCapabilityTask mTask;
281         public String mReason;
282     }
283 
284     public class MessageHandler extends Handler{
MessageHandler(Looper looper)285         MessageHandler(Looper looper){
286             super(looper);
287         }
288 
289         @Override
handleMessage(Message msg)290         public void handleMessage(Message msg) {
291             super.handleMessage(msg);
292 
293             logger.debug( "Thread=" + Thread.currentThread().getName() + " received "
294                     + msg);
295 
296 
297 
298             if(msg == null){
299                 logger.error("msg=null");
300                 return;
301             }
302 
303             switch (msg.what) {
304                 case  TASK_MANAGER_ON_TERMINATED:
305                 {
306                     MessageData messageData = (MessageData) msg.obj;
307                     if(messageData != null && messageData.mTask != null){
308                         messageData.mTask.onTerminated(messageData.mReason);
309                     }
310                     break;
311                 }
312 
313                 case TASK_MANAGER_ON_TIMEOUT:
314                 {
315                     MessageData messageData = (MessageData) msg.obj;
316                     if(messageData != null && messageData.mTask != null){
317                         messageData.mTask.onTimeout();
318                     }
319                     break;
320                 }
321 
322                 default:
323                     logger.debug("handleMessage unknown msg=" + msg.what);
324             }
325         }
326     }
327 
clearTimeoutAvailabilityTask(long availabilityExpire)328     public void clearTimeoutAvailabilityTask(long availabilityExpire) {
329        logger.debug("clearTimeoutAvailabilityTask");
330 
331         synchronized (mSyncObj) {
332             long currentTime = System.currentTimeMillis();
333 
334             Iterator<Map.Entry<String, Task>> iterator = mTaskMap.entrySet().iterator();
335             while (iterator.hasNext()) {
336                 Map.Entry<String, Task> entry = iterator.next();
337 
338                 Task task = (Task) entry.getValue();
339                 logger.debug("Currently existing Availability task, key: " + entry.getKey()
340                         + ", Task: " + task);
341 
342                 if ((task != null) && (task instanceof PresenceAvailabilityTask)) {
343                     PresenceAvailabilityTask presenceTask = (PresenceAvailabilityTask)task;
344 
345                     long notifyTimestamp = presenceTask.getNotifyTimestamp();
346                     long createTimestamp = presenceTask.getCreateTimestamp();
347                     logger.debug("createTimestamp=" + createTimestamp + " notifyTimestamp=" +
348                             notifyTimestamp + " currentTime=" + currentTime);
349 
350                      // remove it if it didn't get notify in 60s.
351                      // or get notify for 60s
352                     if(((notifyTimestamp != 0) &&
353                             (notifyTimestamp + availabilityExpire < currentTime)) ||
354                             (notifyTimestamp == 0) &&
355                             (createTimestamp + availabilityExpire < currentTime)) {
356                         logger.debug("remove expired availability task:" + presenceTask);
357                         iterator.remove();
358                     }
359                 }
360             }
361         }
362     }
363 
getAvailabilityTaskByContact(String contact)364     public PresenceAvailabilityTask getAvailabilityTaskByContact(String contact){
365         synchronized (mSyncObj){
366             Set<String> keys= mTaskMap.keySet();
367             if(keys == null){
368                 logger.debug("getTaskByContact keys=null");
369                 return null;
370             }
371 
372             for(String key:keys){
373                 Task task = mTaskMap.get(key);
374                 if(task == null){
375                     continue;
376                 }
377 
378                 if(task instanceof PresenceAvailabilityTask){
379                     PresenceAvailabilityTask availabilityTask = (PresenceAvailabilityTask)task;
380                     if(PhoneNumberUtils.compare(contact, availabilityTask.mContacts[0])){
381                         return availabilityTask;
382                     }
383                 }
384             }
385         }
386 
387         return null;
388     }
389 }
390 
391