• 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.presence;
30 
31 import android.annotation.IntDef;
32 import android.content.Context;
33 import android.content.Intent;
34 import android.telephony.ims.ImsManager;
35 
36 import com.android.ims.ResultCode;
37 import com.android.ims.internal.Logger;
38 import com.android.service.ims.Task;
39 import com.android.service.ims.TaskManager;
40 
41 import java.lang.annotation.Retention;
42 import java.lang.annotation.RetentionPolicy;
43 import java.util.Arrays;
44 
45 public class PresenceBase {
46     static private Logger logger = Logger.getLogger("PresenceBase");
47 
48     protected Context mContext;
49 
50     /**
51      * The phone is PUBLISH_STATE_200_OK when
52      * the response of the last publish is "200 OK"
53      */
54     public static final int PUBLISH_STATE_200_OK = 0;
55 
56     /**
57      * The phone didn't publish after power on.
58      * the phone didn't get any publish response yet.
59      */
60     public static final int PUBLISH_STATE_NOT_PUBLISHED = 1;
61 
62     /**
63      * The phone is PUBLISH_STATE_VOLTE_PROVISION_ERROR when the response is one of items
64      * in config_volte_provision_error_on_publish_response for PUBLISH or
65      * in config_volte_provision_error_on_subscribe_response for SUBSCRIBE.
66      */
67     public static final int PUBLISH_STATE_VOLTE_PROVISION_ERROR = 2;
68 
69     /**
70      * The phone is PUBLISH_STATE_RCS_PROVISION_ERROR when the response is one of items
71      * in config_rcs_provision_error_on_publish_response for PUBLISH or
72      * in config_rcs_provision_error_on_subscribe_response for SUBSCRIBE.Publ
73      */
74     public static final int PUBLISH_STATE_RCS_PROVISION_ERROR = 3;
75 
76     /**
77      * The phone is PUBLISH_STATE_REQUEST_TIMEOUT when
78      * The response of the last publish is "408 Request Timeout".
79      */
80     public static final int PUBLISH_STATE_REQUEST_TIMEOUT = 4;
81 
82     /**
83      * The phone is PUBLISH_STATE_OTHER_ERROR when
84      * the response of the last publish is other temp error. Such as
85      * 503 Service Unavailable
86      * Device shall retry with exponential back-off
87      *
88      * 423 Interval Too Short. Requested expiry interval too short and server rejects it
89      * Device shall re-attempt subscription after changing the expiration interval in
90      * the Expires header field to be equal to or greater than the expiration interval
91      * within the Min-Expires header field of the 423 response.
92      */
93     public static final int PUBLISH_STATE_OTHER_ERROR = 5;
94 
95     @IntDef(value = {
96             PUBLISH_STATE_200_OK,
97             PUBLISH_STATE_NOT_PUBLISHED,
98             PUBLISH_STATE_VOLTE_PROVISION_ERROR,
99             PUBLISH_STATE_RCS_PROVISION_ERROR,
100             PUBLISH_STATE_REQUEST_TIMEOUT,
101             PUBLISH_STATE_OTHER_ERROR
102     }, prefix="PUBLISH_STATE_")
103     @Retention(RetentionPolicy.SOURCE)
104     public @interface PresencePublishState {}
105 
PresenceBase(Context context)106     public PresenceBase(Context context) {
107         mContext = context;
108     }
109 
handleCallback(Task task, int resultCode, boolean forCmdStatus)110     protected void handleCallback(Task task, int resultCode, boolean forCmdStatus) {
111         if (task == null) {
112             logger.debug("task == null");
113             return;
114         }
115 
116         if (task.mListener != null) {
117             if(resultCode >= ResultCode.SUCCESS){
118                 if(!forCmdStatus){
119                     task.mListener.onSuccess(task.mTaskId);
120                 }
121             }else{
122                 task.mListener.onError(task.mTaskId, resultCode);
123             }
124         }
125 
126         // remove task when error
127         // remove task when SIP response success.
128         // For list capability polling we will waiting for the terminated notify or timeout.
129         if (resultCode != ResultCode.SUCCESS) {
130             if(task instanceof PresencePublishTask){
131                 PresencePublishTask publishTask = (PresencePublishTask) task;
132                 logger.debug("handleCallback for publishTask=" + publishTask);
133                 if(resultCode == PUBLISH_STATE_VOLTE_PROVISION_ERROR) {
134                     // retry 3 times for "403 Not Authorized for Presence".
135                     if (publishTask.getRetryCount() >= 3) {
136                         //remove capability after try 3 times by PresencePolling
137                         logger.debug("handleCallback remove task=" + task);
138                         TaskManager.getDefault().removeTask(task.mTaskId);
139                     } else {
140                         // Continue retry
141                         publishTask.setRetryCount(publishTask.getRetryCount() + 1);
142                     }
143                 } else {
144                     logger.debug("handleCallback remove task=" + task);
145                     TaskManager.getDefault().removeTask(task.mTaskId);
146                 }
147             } else {
148                 logger.debug("handleCallback remove task=" + task);
149                 TaskManager.getDefault().removeTask(task.mTaskId);
150             }
151         }else{
152             if(forCmdStatus || !forCmdStatus && (task instanceof PresenceCapabilityTask)){
153                 logger.debug("handleCallback remove task later");
154 
155                 //waiting for Notify from network
156                 if(!forCmdStatus){
157                     ((PresenceCapabilityTask)task).setWaitingForNotify(true);
158                 }
159             }else{
160                 if(!forCmdStatus && (task instanceof PresenceAvailabilityTask) &&
161                         (resultCode == ResultCode.SUCCESS)){
162                     // Availiablity, cache for 60s, remove it later.
163                     logger.debug("handleCallback PresenceAvailabilityTask cache for 60s task="
164                             + task);
165                     return;
166                 }
167 
168                 logger.debug("handleCallback remove task=" + task);
169                 TaskManager.getDefault().removeTask(task.mTaskId);
170             }
171         }
172     }
173 
onCommandStatusUpdated(int taskId, int requestId, int resultCode)174     public void onCommandStatusUpdated(int taskId, int requestId, int resultCode) {
175         Task task = TaskManager.getDefault().getTask(taskId);
176         if (task != null){
177             task.mSipRequestId = requestId;
178             task.mCmdStatus = resultCode;
179             TaskManager.getDefault().putTask(task.mTaskId, task);
180         }
181 
182         handleCallback(task, resultCode, true);
183     }
184 
notifyDm()185     protected void notifyDm() {
186         logger.debug("notifyDm");
187         Intent intent = new Intent(
188                 ImsManager.ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION);
189         intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
190 
191         mContext.sendBroadcast(intent);
192     }
193 
isInConfigList(int errorNo, String phrase, String[] errorArray)194     protected boolean isInConfigList(int errorNo, String phrase, String[] errorArray) {
195         String inErrorString = ("" + errorNo).trim();
196 
197         logger.debug("errorArray length=" + errorArray.length
198                 + " errorArray=" + Arrays.toString(errorArray));
199         for (String errorStr : errorArray) {
200             if (errorStr != null && errorStr.startsWith(inErrorString)) {
201                 String errorPhrase = errorStr.substring(inErrorString.length());
202                 if(errorPhrase == null || errorPhrase.isEmpty()) {
203                     return true;
204                 }
205 
206                 if(phrase == null || phrase.isEmpty()) {
207                     return false;
208                 }
209 
210                 return phrase.toLowerCase().contains(errorPhrase.toLowerCase());
211             }
212         }
213         return false;
214     }
215 }
216 
217